从string中删除所有空白的有效方法?

我正在调用一个REST API,并且正在接收一个XML响应。 它返回一个工作区名称列表,并且正在编写一个快速的IsExistingWorkspace()方法。 由于所有的工作空间都是由没有空格的连续字符组成的,所以我假设find一个特定工作空间是否在列表中的最简单的方法是删除所有的空格(包括换行符)并且这样做(XML是从networking接收到的string请求):

 XML.Contains("<name>" + workspaceName + "</name>"); 

我知道这是区分大小写的,我依靠这个。 我只需要一种方法来有效地删除string中的所有空格。 我知道正则expression式和LINQ可以做到这一点,但我打开其他的想法。 我大多只关心速度。

这是我知道的最快的方法,即使你说你不想使用正则expression式:

 Regex.Replace(XML, @"\s+", "") 

我有一个没有正则expression式的替代方法,它似乎performance相当不错。 这是Brandon Moretz的延续答案:

  public static string RemoveWhitespace(this string input) { return new string(input.ToCharArray() .Where(c => !Char.IsWhiteSpace(c)) .ToArray()); } 

我在一个简单的unit testing中testing了它:

 [Test] [TestCase("123 123 1adc \n 222", "1231231adc222")] public void RemoveWhiteSpace1(string input, string expected) { string s = null; for (int i = 0; i < 1000000; i++) { s = input.RemoveWhitespace(); } Assert.AreEqual(expected, s); } [Test] [TestCase("123 123 1adc \n 222", "1231231adc222")] public void RemoveWhiteSpace2(string input, string expected) { string s = null; for (int i = 0; i < 1000000; i++) { s = Regex.Replace(input, @"\s+", ""); } Assert.AreEqual(expected, s); } 

对于1,000,000次尝试,第一个选项(没有正则expression式)在less于一秒(我的机器上是700毫秒)内运行,第二个选项需要3.5秒。

尝试在C#中的string的replace方法。

 XML.Replace(" ", string.Empty); 

我的解决scheme是使用拆分和连接,这是令人惊讶的快速,实际上是最快的答案在这里。

 str = string.Join("", str.Split(default(string[]), StringSplitOptions.RemoveEmptyEntries)); 

用简单的string与空白的10,000循环时间包括新行和制表符

  • 分割/连接= 60毫秒
  • linq chararray = 94毫秒
  • 正则expression式= 437毫秒

通过将其包装在方法中来提高它的意义,并使之成为扩展方法。

 public static string RemoveWhitespace(this string str) { return string.Join("", str.Split(default(string[]), StringSplitOptions.RemoveEmptyEntries)); } 

只是一个替代品,因为它看起来相当不错:) – 注意: 亨克斯答案是最快的这些。

 input.ToCharArray() .Where(c => !Char.IsWhiteSpace(c)) .Select(c => c.ToString()) .Aggregate((a, b) => a + b); 

testing1,000,000个循环"This is a simple Test"

这个方法= 1.74秒
正则expression式= 2.58秒
new String (Henks)= 0.82

build立在Henks的答案我已经创build了一些testing方法与他的答案和一些添加,更优化的方法。 我发现结果根据inputstring的大小而有所不同。 所以我testing了两个结果集。 用最快的方法,链接的源代码有更快的方法。 但是,既然它的特点是不安全的,我已经把这个留给了。

长inputstring结果:

  1. InPlaceCharArray:2021毫秒( Sunsetquest的答案 ) – ( 原始来源 )
  2. string阅读器:6082毫秒
  3. LINQ使用本机char.IsWhitespace:7357毫秒
  4. LINQ:7746 ms( Henk的回答 )
  5. ForLoop:32320毫秒
  6. 正则expression式编译:37157毫秒
  7. 正则expression式:42940毫秒

短的inputstring结果:

  1. InPlaceCharArray:108毫秒( Sunsetquest的答案 ) – ( 原始来源 )
  2. string阅读器:327毫秒
  3. ForLoop:343毫秒
  4. LINQ使用本机char.IsWhitespace:624毫秒
  5. LINQ:645ms( Henk的回答 )
  6. 正则expression式编译:1671毫秒
  7. 正则expression式:2599毫秒

代码

 public class RemoveWhitespace { public static string RemoveStringReader(string input) { var s = new StringBuilder(input.Length); // (input.Length); using (var reader = new StringReader(input)) { int i = 0; char c; for (; i < input.Length; i++) { c = (char)reader.Read(); if (!char.IsWhiteSpace(c)) { s.Append(c); } } } return s.ToString(); } public static string RemoveLinqNativeCharIsWhitespace(string input) { return new string(input.ToCharArray() .Where(c => !char.IsWhiteSpace(c)) .ToArray()); } public static string RemoveLinq(string input) { return new string(input.ToCharArray() .Where(c => !Char.IsWhiteSpace(c)) .ToArray()); } public static string RemoveRegex(string input) { return Regex.Replace(input, @"\s+", ""); } private static Regex compiled = new Regex(@"\s+", RegexOptions.Compiled); public static string RemoveRegexCompiled(string input) { return compiled.Replace(input, ""); } public static string RemoveForLoop(string input) { for (int i = input.Length - 1; i >= 0; i--) { if (char.IsWhiteSpace(input[i])) { input = input.Remove(i, 1); } } return input; } public static string RemoveInPlaceCharArray(string input) { var len = input.Length; var src = input.ToCharArray(); int dstIdx = 0; for (int i = 0; i < len; i++) { var ch = src[i]; switch (ch) { case '\u0020': case '\u00A0': case '\u1680': case '\u2000': case '\u2001': case '\u2002': case '\u2003': case '\u2004': case '\u2005': case '\u2006': case '\u2007': case '\u2008': case '\u2009': case '\u200A': case '\u202F': case '\u205F': case '\u3000': case '\u2028': case '\u2029': case '\u0009': case '\u000A': case '\u000B': case '\u000C': case '\u000D': case '\u0085': continue; default: src[dstIdx++] = ch; break; } } return new string(src, 0, dstIdx); } } 

testing

 [TestFixture] public class Test { // Short input //private const string input = "123 123 \t 1adc \n 222"; //private const string expected = "1231231adc222"; // Long input private const string input = "123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222"; private const string expected = "1231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc222"; private const int iterations = 1000000; [Test] public void RemoveInPlaceCharArray() { string s = null; var stopwatch = Stopwatch.StartNew(); for (int i = 0; i < iterations; i++) { s = RemoveWhitespace.RemoveInPlaceCharArray(input); } stopwatch.Stop(); Console.WriteLine("InPlaceCharArray: " + stopwatch.ElapsedMilliseconds + " ms"); Assert.AreEqual(expected, s); } [Test] public void RemoveStringReader() { string s = null; var stopwatch = Stopwatch.StartNew(); for (int i = 0; i < iterations; i++) { s = RemoveWhitespace.RemoveStringReader(input); } stopwatch.Stop(); Console.WriteLine("String reader: " + stopwatch.ElapsedMilliseconds + " ms"); Assert.AreEqual(expected, s); } [Test] public void RemoveLinqNativeCharIsWhitespace() { string s = null; var stopwatch = Stopwatch.StartNew(); for (int i = 0; i < iterations; i++) { s = RemoveWhitespace.RemoveLinqNativeCharIsWhitespace(input); } stopwatch.Stop(); Console.WriteLine("LINQ using native char.IsWhitespace: " + stopwatch.ElapsedMilliseconds + " ms"); Assert.AreEqual(expected, s); } [Test] public void RemoveLinq() { string s = null; var stopwatch = Stopwatch.StartNew(); for (int i = 0; i < iterations; i++) { s = RemoveWhitespace.RemoveLinq(input); } stopwatch.Stop(); Console.WriteLine("LINQ: " + stopwatch.ElapsedMilliseconds + " ms"); Assert.AreEqual(expected, s); } [Test] public void RemoveRegex() { string s = null; var stopwatch = Stopwatch.StartNew(); for (int i = 0; i < iterations; i++) { s = RemoveWhitespace.RemoveRegex(input); } stopwatch.Stop(); Console.WriteLine("Regex: " + stopwatch.ElapsedMilliseconds + " ms"); Assert.AreEqual(expected, s); } [Test] public void RemoveRegexCompiled() { string s = null; var stopwatch = Stopwatch.StartNew(); for (int i = 0; i < iterations; i++) { s = RemoveWhitespace.RemoveRegexCompiled(input); } stopwatch.Stop(); Console.WriteLine("RegexCompiled: " + stopwatch.ElapsedMilliseconds + " ms"); Assert.AreEqual(expected, s); } [Test] public void RemoveForLoop() { string s = null; var stopwatch = Stopwatch.StartNew(); for (int i = 0; i < iterations; i++) { s = RemoveWhitespace.RemoveForLoop(input); } stopwatch.Stop(); Console.WriteLine("ForLoop: " + stopwatch.ElapsedMilliseconds + " ms"); Assert.AreEqual(expected, s); } } 

如果你需要高超的性能,在这种情况下你应该避免使用LINQ和正则expression式。 我做了一些性能基准testing,看起来如果你想从string的开头和结尾去掉空格,string.Trim()是你的最终function。

如果你需要从string中去掉所有的空格,下面的方法在这里发布的所有东西中运行速度最快:

  public static string RemoveWhitespace(this string input) { int j = 0, inputlen = input.Length; char[] newarr = new char[inputlen]; for (int i = 0; i < inputlen; ++i) { char tmp = input[i]; if (!char.IsWhiteSpace(tmp)) { newarr[j] = tmp; ++j; } } return new String(newarr, 0, j); } 

我在CodeProject 上find了一篇关于 Felipe Machado的好书( Richard Robertson的帮助)

他testing了十种不同的方法。 这是最快的不安全的版本…

 public static unsafe string TrimAllWithStringInplace(string str) { fixed (char* pfixed = str) { char* dst = pfixed; for (char* p = pfixed; *p != 0; p++) switch (*p) { case '\u0020': case '\u00A0': case '\u1680': case '\u2000': case '\u2001': case '\u2002': case '\u2003': case '\u2004': case '\u2005': case '\u2006': case '\u2007': case '\u2008': case '\u2009': case '\u200A': case '\u202F': case '\u205F': case '\u3000': case '\u2028': case '\u2029': case '\u0009': case '\u000A': case '\u000B': case '\u000C': case '\u000D': case '\u0085': continue; default: *dst++ = *p; break; } return new string(pfixed, 0, (int)(dst - pfixed)); } 

而最安全的版本…

 public static string TrimAllWithInplaceCharArray(string str) { var len = str.Length; var src = str.ToCharArray(); int dstIdx = 0; for (int i = 0; i < len; i++) { var ch = src[i]; switch (ch) { case '\u0020': case '\u00A0': case '\u1680': case '\u2000': case '\u2001': case '\u2002': case '\u2003': case '\u2004': case '\u2005': case '\u2006': case '\u2007': case '\u2008': case '\u2009': case '\u200A': case '\u202F': case '\u205F': case '\u3000': case '\u2028': case '\u2029': case '\u0009': case '\u000A': case '\u000B': case '\u000C': case '\u000D': case '\u0085': continue; default: src[dstIdx++] = ch; break; } } return new string(src, 0, dstIdx); } 

Stian Standahl的堆栈溢出也有一些很好的独立基准 ,也显示了Felipe的函数比下一个最快函数快300%。

正则expression式是过度的; 只需使用扩展string(感谢亨克)。 这是微不足道的,应该是框架的一部分。 无论如何,这是我的实现:

 public static partial class Extension { public static string RemoveWhiteSpace(this string self) { return new string(self.Where(c => !Char.IsWhiteSpace(c)).ToArray()); } } 

这是一个RegEx解决scheme的简单线性替代scheme。 我不确定哪一个更快。 你必须对它进行基准testing。

 static string RemoveWhitespace(string input) { StringBuilder output = new StringBuilder(input.Length); for (int index = 0; index < input.Length; index++) { if (!Char.IsWhiteSpace(input, index)) { output.Append(input[index]); } } return output.ToString(); } 

我假设你的XML响应如下所示:

 var xml = @"<names> <name> foo </name> <name> bar </name> </names>"; 

处理XML的最好方法是使用XMLparsing器,例如LINQ to XML

 var doc = XDocument.Parse(xml); var containsFoo = doc.Root .Elements("name") .Any(e => ((string)e).Trim() == "foo"); 

我需要用空格replacestring中的空格,但不能重复空格。 例如,我需要转换如下所示:

 "abc\r\nd\t\t\te" 

 "abcde" 

我用了下面的方法

 private static string RemoveWhiteSpace(string value) { if (value == null) { return null; } var sb = new StringBuilder(); var lastCharWs = false; foreach (var c in value) { if (char.IsWhiteSpace(c)) { if (lastCharWs) { continue; } sb.Append(' '); lastCharWs = true; } else { sb.Append(c); lastCharWs = false; } } return sb.ToString(); } 

我发现不同的结果是正确的。 我试图用一个空格replace所有的空格,正则expression式非常慢。

 return( Regex::Replace( text, L"\s+", L" " ) ); 

对于我来说最合适的(C ++ cli)是:

 String^ ReduceWhitespace( String^ text ) { String^ newText; bool inWhitespace = false; Int32 posStart = 0; Int32 pos = 0; for( pos = 0; pos < text->Length; ++pos ) { wchar_t cc = text[pos]; if( Char::IsWhiteSpace( cc ) ) { if( !inWhitespace ) { if( pos > posStart ) newText += text->Substring( posStart, pos - posStart ); inWhitespace = true; newText += L' '; } posStart = pos + 1; } else { if( inWhitespace ) { inWhitespace = false; posStart = pos; } } } if( pos > posStart ) newText += text->Substring( posStart, pos - posStart ); return( newText ); } 

我首先尝试了上面的例程,分别replace每个字符,但不得不切换到非空格部分的子string。 应用于1,200,000个字符的string时:

  • 上面的例程在25秒内完成
  • 上面的例程+ 95秒内单独的字符replace
  • 正则expression式在15分钟后中止。

这是又一个变种:

 public static string RemoveAllWhitespace(string aString) { return String.Join(String.Empty, aString.Where(aChar => aChar !Char.IsWhiteSpace(aChar))); } 

与大多数其他解决scheme一样,我没有进行彻底的基准testing,但是这对我的目的来说已经足够了。

我们可以用:

  public static string RemoveWhitespace(this string input) { if (input == null) return null; return new string(input.ToCharArray() .Where(c => !Char.IsWhiteSpace(c)) .ToArray()); } 

假设我们有这个string: string MyString = " test test test" 。 你可以用一个空格分隔符来分割你的string: MyString.Split(' ') 。 它会产生空string和其他章程的数组。 在这种情况下,它会生成这个数组: { "", "test", "test", "", "", "", "test" } 。 然后使用string.concat方法可以连接数组中所有导致"testtesttest"string。

 string MyString = " test test test"; MyString = string.Concat(MyString.Split(' ')); 

我们可以使用System.Linq,我们可以在一行中完成:

 string text = "My text with white spaces..."; text = new string(text.ToList().Where(c => c != ' ').ToArray()); 
 String s = Console.ReadLine(); s = s.Replace(" ", String.Empty); String[] arr = s.Split(' '); foreach(char num in s) { Console.WriteLine(num); } 

这段代码将删除string中的所有空格。