如何用C#中的一个空格替换字符串中的多个空格?

示例:

1 2 3  4    5


将是:

1 2 3 4 5


评论

一个状态机可以轻松地做到这一点,但是如果只需要删除空格就可能会被杀了

我在重复的问题stackoverflow.com/a/37592018/582061中添加了执行此操作的不同方法的基准。正则表达式不是最快的方法。

#1 楼

string sentence = "This is a sentence with multiple    spaces";
RegexOptions options = RegexOptions.None;
Regex regex = new Regex("[ ]{2,}", options);     
sentence = regex.Replace(sentence, " ");


评论


我已经复制并粘贴了它,并且可以正常工作。我真的不喜欢REgex,但这一次可以挽救我的生命。

– Pokus
08-10-15在22:22

IMO,@ Craig评论就足够了。 //此块用一个...替换多个空格:)

–paulwhit
08-10-15在23:40

确实,RegEx在这方面过于矫kill过正。

–乔尔·科恩(Joel Coehoorn)
08-10-28在15:01

@乔尔:不同意。实际上,我可以肯定,对于足够大的字符串,这种方法比您更有效,并且可以在一行中完成。过度杀伤在哪里?

–康拉德·鲁道夫(Konrad Rudolph)
08年11月23日在16:27

@Oscar Joel的代码并不是遍历所有角色的简单循环!这是一个隐藏的嵌套循环,具有二次最坏的情况。相比之下,此正则表达式是线性的,只能建立一个字符串(与Joel的代码相比,=大大降低了分配成本),此外,引擎可以对其进行优化(说实话,我怀疑.NET regex是否是这样做足够聪明,但是从理论上讲,这种正则表达式可以以非常便宜的方式实现,以至于不再有趣;它只需要DFA包含三个状态,每个状态一个转换,而无需其他信息。

–康拉德·鲁道夫(Konrad Rudolph)
2011年3月4日10:17



#2 楼

我喜欢使用:

myString = Regex.Replace(myString, @"\s+", " ");


,因为它将捕获任何类型的空格(例如制表符,换行符等),并用单个空格替换它们。

评论


轻微修改:Regex.Replace(source,@“(\ s)\ s +”,“ $ 1”);这将返回找到的第一个空白类型。因此,如果您有5个标签,它将返回一个标签。如果有人喜欢这个。

– F.B.十个凯特
2012年5月14日12:56

@radistao您的链接用于替换Javascript字符串,而不用于C#。

–湿婆
2014年4月28日在17:58

@Shiva,/ \ s \ s + /是标准的POSIX regex语句,可以使用自己的语法以任何语言转换/使用

–radistao
2014年4月29日在6:45

本着@ F.B.tenKate解决方案的精神:Regex.Replace(source,@“(\ s)\ 1+”,“ $ 1”);会将多个相同的连续字符替换为一个字符。

–FrançoisBeaune
16年1月11日在17:06

为了删除开头和结尾的空格,您应该对此使用Trim()函数,例如var myString = Regex.Replace(myString,@“ \ s +”,“”).Trim();

– Harish Nayak
19年4月3日在2:07

#3 楼

string xyz = "1   2   3   4   5";
xyz = string.Join( " ", xyz.Split( new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries ));


评论


这比regex更具可读性,我更喜欢它,因为我不需要学习其他语法

–迈克尔·巴希格(Michael Bahig)
15年7月24日在11:56

我喜欢它,因为它不需要正则表达式

– AleX_
15年12月22日在18:08

这对于大字符串将是低效的。

– DarcyThomas
16-09-28在4:05

这也将删除前导和尾随空格。

–马齐
17年2月5日21:00

我也更喜欢这个答案。我的老导师曾经说过:“每当您遇到问题时,您就认为需要Regex解决,好吧……现在您遇到了两个问题”

–小威廉·麦当娜(William Madonna Jr.)
18年4月6日在12:53

#4 楼

我认为Matt的答案是最好的,但我不认为这是正确的。如果要替换换行符,则必须使用:

myString = Regex.Replace(myString, @"\s+", " ", RegexOptions.Multiline);


评论


RegexOptions.Multiline更改^和$的含义,因此它们匹配每行的开始和结尾($ = \ n),而不是整个多行字符串。由于\ s等效于[\ f \ n \ r \ t \ v],即使关闭了“多行”选项,也应替换换行符。

– SushiGuy
2012年6月5日23:27

马特的答案已经涵盖了这一点。我“相信” 30个人,只是蒙住了眼睛投票赞成这个答案:)

–123iamking
2017年9月8日在3:50



#5 楼

使用LINQ的另一种方法:

 var list = str.Split(' ').Where(s => !string.IsNullOrWhiteSpace(s));
 str = string.Join(" ", list);


#6 楼

即使执行简单的任务,正则表达式也可能相当慢。这将创建可在任何string之外使用的扩展方法。

    public static class StringExtension
    {
        public static String ReduceWhitespace(this String value)
        {
            var newString = new StringBuilder();
            bool previousIsWhitespace = false;
            for (int i = 0; i < value.Length; i++)
            {
                if (Char.IsWhiteSpace(value[i]))
                {
                    if (previousIsWhitespace)
                    {
                        continue;
                    }

                    previousIsWhitespace = true;
                }
                else
                {
                    previousIsWhitespace = false;
                }

                newString.Append(value[i]);
            }

            return newString.ToString();
        }
    }


可以这样使用:

string testValue = "This contains     too          much  whitespace."
testValue = testValue.ReduceWhitespace();
// testValue = "This contains too much whitespace."


评论


尽管可以优化例程,但我喜欢扩展方法的想法。

–henda79
12月17日9:30

#7 楼

它比所有简单得多:

while(str.Contains("  ")) str = str.Replace("  ", " ");


评论


如果字符串包含3个或更多空格的序列,这将比正则表达式“ {2,}”的效率低得多。

– Jan Goyvaerts
08年11月20日在7:22

@JanGoyvaerts:即使有10个空格,当我进行快速而肮脏的测试时,正则表达式也较慢。话虽如此,它只需要一个充满空格的巨型子串就可以完全杀死while循环的性能。为了公平起见,我使用了RegexOptions.Compiled,而不是较慢的Regex.Replace。

–布赖恩
2013年2月6日15:37



RegexOptions.Compiled增加了很多将正则表达式编译为IL的开销。除非您的应用程序经常使用正则表达式或在足够大的字符串上使用正则表达式,否则增加的匹配速度可以抵消降低的编译速度,请不要使用它。

– Jan Goyvaerts
13年2月7日在4:26

这是效率极低的示例。大声笑。

– pcbabu
2月19日19:51

@pcbabu这并不像很多情况下看起来那么糟糕。 Replace()方法将处理给定字符串中两个空格的所有出现,因此我们不会为字符串中配对空格的每个实例循环(并重新分配整个字符串)。一种新的分配将处理所有这些分配。我们只有在3个或3个以上的空格在一起时才重新运行循环,这对于许多输入源来说可能很少见。如果可以显示出它成为数据问题,那么请编写状态机以将一个字符一个字符地推送到新的stringbuilder中。

–乔尔·科恩(Joel Coehoorn)
2月19日在22:24



#8 楼

myString = Regex.Replace(myString, " {2,}", " ");


#9 楼

对于不喜欢Regex的用户,以下是使用StringBuilder的方法:

    public static string FilterWhiteSpaces(string input)
    {
        if (input == null)
            return string.Empty;

        StringBuilder stringBuilder = new StringBuilder(input.Length);
        for (int i = 0; i < input.Length; i++)
        {
            char c = input[i];
            if (i == 0 || c != ' ' || (c == ' ' && input[i - 1] != ' '))
                stringBuilder.Append(c);
        }
        return stringBuilder.ToString();
    }


在我的测试中,该方法的平均速度为16倍与静态已编译的Regex相比,包含大量的中小型字符串。与非编译或非静态Regex相比,它应该更快。

请记住,它不会删除前导或尾随空格,只会多次出现此类。

评论


如果要检查字符是否为空格,而不仅仅是空格,请参阅下面的答案。

–收获
19-11-14在4:22



#10 楼

您只需在一行解决方案中执行此操作即可。

string s = "welcome to  london";
s.Replace(" ", "()").Replace(")(", "").Replace("()", " ");


如果愿意,您可以选择其他方括号(甚至其他字符)。

评论


您必须确保字符串中没有“()”或“)(”,或者“ wel()来到伦敦)(”变成“ wel来到伦敦”。您可以尝试使用很多方括号。因此请使用((((((()))))代替()和))))))((((((代替)(。它仍然可以工作。但是,如果字符串包含(((((()] )))或))))))(((((

–nmit026
17年7月26日在22:18



#11 楼

这是一个较短的版本,仅在您仅执行一次时才应使用,因为它每次调用时都会创建Regex类的新实例。

temp = new Regex(" {2,}").Replace(temp, " "); 


如果您不太熟悉正则表达式,则有一个简短的解释:

{2,}使regex搜索其前面的字符,并找到2到无限次之间的子字符串。
.Replace(temp, " ")用空格替换字符串temp中的所有匹配项。

如果要多次使用,这是一个更好的选择,因为它在编译时创建了正则表达式IL:

Regex singleSpacify = new Regex(" {2,}", RegexOptions.Compiled);
temp = singleSpacify.Replace(temp, " ");


#12 楼

没有正则表达式,没有Linq ...删除前导和尾随空格,以及将任何嵌入的多个空格分段减少为一个空格

string myString = "   0 1 2  3   4               5  ";
myString = string.Join(" ", myString.Split(new char[] { ' ' }, 
StringSplitOptions.RemoveEmptyEntries));


结果:“ 0 1 2 3 4 5英寸

评论


提醒您:使用split尽管确实很容易理解,但却会对性能产生令人惊讶的负面影响。由于可以创建许多字符串,因此如果使用此方法处理大字符串,则必须注意内存使用情况。

– Pac0
18 Jun 25'15:26



#13 楼

按照Joel的建议,总结其他答案,并希望随着我的进行略微改善:

您可以使用Regex.Replace()来做到这一点:

string s = Regex.Replace (
    "   1  2    4 5", 
    @"[ ]{2,}", 
    " "
    );


String.Split()

static class StringExtensions
{
    public static string Join(this IList<string> value, string separator)
    {
        return string.Join(separator, value.ToArray());
    }
}

//...

string s = "     1  2    4 5".Split (
    " ".ToCharArray(), 
    StringSplitOptions.RemoveEmptyEntries
    ).Join (" ");


#14 楼

我刚刚写了一个我喜欢的新Join,所以我想用它来回答:

public static string Join<T>(this IEnumerable<T> source, string separator)
{
    return string.Join(separator, source.Select(e => e.ToString()).ToArray());
}


关于这个的一个很酷的事情是它通过在元素上调用ToString()来处理不是字符串的集合。用法仍然相同:

//...

string s = "     1  2    4 5".Split (
    " ".ToCharArray(), 
    StringSplitOptions.RemoveEmptyEntries
    ).Join (" ");


评论


为什么要创建扩展方法?为什么不只使用string.Join()?

–埃里克·舒恩诺夫
08年11月20日在3:45

#15 楼

// Mysample string
string str ="hi you           are          a demo";

//Split the words based on white sapce
var demo= str .Split(' ').Where(s => !string.IsNullOrWhiteSpace(s));
        
//Join the values back and add a single space in between
str = string.Join(" ", demo);
// output: string str ="hi you are a demo";


#16 楼

我知道这已经很老了,但是在尝试完成几乎同一件事时遇到了这个问题。在RegEx Buddy中找到了此解决方案。此模式将用单个空格替换所有双精度空格,并修剪前导和尾随空格。

pattern: (?m:^ +| +$|( ){2,})
replacement: 


由于我们正在处理空白空间,因此很难阅读,所以这里还是用“ _”代替了“空格”。

pattern: (?m:^_+|_+$|(_){2,})  <-- don't use this, just for illustration.


“(??:”构造启用“多行”选项。我通常喜欢在模式本身中包括我可以使用的任何选项,因此更多自我。

#17 楼

许多答案提供了正确的输出,但是对于那些寻求最佳性能的人,我确实将Nolanar的答案(这是性能的最佳答案)提高了约10%。

public static string MergeSpaces(this string str)
{

    if (str == null)
    {
        return null;
    }
    else
    {
        StringBuilder stringBuilder = new StringBuilder(str.Length);

        int i = 0;
        foreach (char c in str)
        {
            if (c != ' ' || i == 0 || str[i - 1] != ' ')
                stringBuilder.Append(c);
            i++;
        }
        return stringBuilder.ToString();
    }

}


#18 楼

我可以使用此

while word.contains("  ")  //double space
   word = word.Replace("  "," "); //replace double space by single space.
word = word.trim(); //to remove single whitespces from start & end.

删除空格

评论


是的,但是您只能将两个空白替换为一个。这无助于X个空格

–MGot90
16年7月26日在19:59

While循环将处理所有要删除的双精度空格。

–Learner1947
17年3月28日在16:55

#19 楼

使用正则表达式模式

    [ ]+    #only space

   var text = Regex.Replace(inputString, @"[ ]+", " ");


#20 楼

尝试此方法

private string removeNestedWhitespaces(char[] st)
{
    StringBuilder sb = new StringBuilder();
    int indx = 0, length = st.Length;
    while (indx < length)
    {
        sb.Append(st[indx]);
        indx++;
        while (indx < length && st[indx] == ' ')
            indx++;
        if(sb.Length > 1  && sb[0] != ' ')
            sb.Append(' ');
    }
    return sb.ToString();
}


像这样使用:

string test = removeNestedWhitespaces("1 2 3  4    5".toCharArray());


评论


这将删除尾随空格

– The_Black_Smurf
18-2-27在19:37

对不起,我修复了代码,现在它可以按预期的方式工作,已测试的字符串:“ 1 2 3 4 9”结果字符串:“ 1 2 3 4 9”

–艾哈迈德·阿尔杰夫(Ahmed Aljaff)
18年8月26日在22:04

#21 楼

这是对Nolonar原始答案的略微修改。

检查字符是否不仅是空格,还包括任何空格,请使用此方法:

它将替换任何多个空格字符一个空格。

public static string FilterWhiteSpaces(string input)
{
    if (input == null)
        return string.Empty;

    var stringBuilder = new StringBuilder(input.Length);
    for (int i = 0; i < input.Length; i++)
    {
        char c = input[i];
        if (i == 0 || !char.IsWhiteSpace(c) || (char.IsWhiteSpace(c) && 
            !char.IsWhiteSpace(strValue[i - 1])))
            stringBuilder.Append(c);
    }
    return stringBuilder.ToString();
}


评论


谢谢,这帮助了我。小错误:应该输入strValue。此外,IsWhiteSpace包含换行符。您可能不想合并多个换行符,仅是因为它会根据您的环境(\ r \ n与\ n)而有所不同。在这种情况下,请检查“ CharUnicodeInfo.GetUnicodeCategory(c)== UnicodeCategory.SpaceSeparator”。

– Oliver Schimmer
7月13日15:57



正确的@OliverSchimmer,感谢您的纠正。添加的unicode字符信息是一个很好的补充。随时进行编辑! :)

–收获
7月13日下午16:31

这不是对答案的重写吗? stackoverflow.com/a/33817748/56621

– Alex
7月15日15:30

#22 楼

老套子:

string oldText = "   1 2  3   4    5     ";
string newText = oldText
                    .Replace("  ", " " + (char)22 )
                    .Replace( (char)22 + " ", "" )
                    .Replace( (char)22 + "", "" );

Assert.That( newText, Is.EqualTo( " 1 2 3 4 5 " ) );


#23 楼

不使用正则表达式:

while (myString.IndexOf("  ", StringComparison.CurrentCulture) != -1)
{
    myString = myString.Replace("  ", " ");
}


可以在短字符串上使用,但是在长空格很多的情况下效果不好。

#24 楼

将StringBuilder和Enumerable.Aggregate()混合用作字符串的扩展方法:

using System;
using System.Linq;
using System.Text;

public static class StringExtension
{
    public static string StripSpaces(this string s)
    {
        return s.Aggregate(new StringBuilder(), (acc, c) =>
        {
            if (c != ' ' || acc.Length > 0 && acc[acc.Length-1] != ' ')
                acc.Append(c);

            return acc;
        }).ToString();
    }

    public static void Main()
    {
        Console.WriteLine("\"" + StringExtension.StripSpaces("1   Hello       World  2   ") + "\"");
    }
}


输入:

"1   Hello       World  2   "


>输出:

"1 Hello World 2 "