【问题标题】:Fastest way to remove white spaces in string删除字符串中空格的最快方法
【发布时间】:2011-03-05 11:46:48
【问题描述】:

我正在尝试从数据库表的字符串中获取多个以“,”分隔的电子邮件地址,但它也返回了空格,我想快速删除空格。

以下代码确实删除了空格,但每当我尝试获取 30000 等字符串中的大量电子邮件地址,然后尝试删除它们之间的空格时,它也会变慢。删除这些空格需要四到五分钟以上的时间。

 Regex Spaces =
        new Regex(@"\s+", RegexOptions.Compiled);
txtEmailID.Text = MultipleSpaces.Replace(emailaddress),"");

谁能告诉我如何在一秒钟内删除空格,即使是大量的电子邮件地址?

【问题讨论】:

标签: c# .net string whitespace


【解决方案1】:

我会使用StringBuilder 构建一个自定义扩展方法,例如:

public static string ExceptChars(this string str, IEnumerable<char> toExclude)
{
    StringBuilder sb = new StringBuilder(str.Length);
    for (int i = 0; i < str.Length; i++)
    {
        char c = str[i];
        if (!toExclude.Contains(c))
            sb.Append(c);
    }
    return sb.ToString();
}

用法:

var str = s.ExceptChars(new[] { ' ', '\t', '\n', '\r' });

或者更快:

var str = s.ExceptChars(new HashSet<char>(new[] { ' ', '\t', '\n', '\r' }));

使用 hashset 版本,1100 万个字符的字符串耗时不到 700 毫秒(我处于调试模式)

编辑:

以前的代码是通用的,允许排除任何字符,但如果你想以最快的方式删除空白,你可以使用:

public static string ExceptBlanks(this string str)
{
    StringBuilder sb = new StringBuilder(str.Length);
    for (int i = 0; i < str.Length; i++)
    {
        char c = str[i];
        switch (c)
        {
            case '\r':
            case '\n':
            case '\t':
            case ' ':
                continue;
            default:
                sb.Append(c);
                break;
        }
    }
    return sb.ToString();
}

编辑 2:

正如 cmets 中正确指出的那样,删除 所有 空白的正确方法是使用 char.IsWhiteSpace 方法:

public static string ExceptBlanks(this string str)
{
    StringBuilder sb = new StringBuilder(str.Length);
    for (int i = 0; i < str.Length; i++)
    {
        char c = str[i];
        if(!char.IsWhiteSpace(c))
            sb.Append(c);
    }
    return sb.ToString();
}

【讨论】:

  • 你可以为这个解决方案创建光速哈希:byte[] hash = new byte[255]; 如果你想排除\t 你做b[(int)'\t'] = 1 然后用同样的方法检查。但它只适用于 ascii :)
  • 是的,那会非常快。否则,如果您只想从字符串中删除空格,您可以直接在函数中使用开关并跳过 IEnumerable.Contains :)
  • 嗯...不错的解决方案,比我的更好:)
  • 最好使用StringBuilder sb = new StringBuilder(str.Length);
  • Char.IsWhiteSpace(c) 比 switch 语句效果更好,并使用输入字符串的长度初始化 stringbuilder 类
【解决方案2】:

鉴于string.Replace的实现是用C++编写的,而CLR runtime的一部分我愿意打赌

email.Replace(" ","").Replace("\t","").Replace("\n","").Replace("\r","");

将是最快的实现。如果你需要every type of whitespace,你可以提供unicode等效的十六进制值。

【讨论】:

  • 是的,这确实很快,但是这会创建 4 个字符串而不是 1 个。如果字符串很长,这会减慢一点,使用 StringBuilder 的自定义实现比这更快。
  • @digEmAll 虽然这是一个电子邮件地址,所以并不占用大量内存。如果它是一个 1k 的大文本文件,我会同意
  • 据我了解,它是一个字符串,有很多电子邮件逗号分隔...但老实说,我不确定...
【解决方案3】:

使用 linq,您可以简单地做到这一点:

emailaddress = new String(emailaddress
                                     .Where(x=>x!=' ' && x!='\r' && x!='\n')
                                     .ToArray());

我没有将它与 stringbuilder 方法进行比较,但它比基于字符串的方法快得多。 因为它不会创建很多字符串的副本(字符串是不可变的,直接使用它会导致显着的内存和速度问题),所以它不会使用非常大的内存并且不会降低速度(除了一个额外的通过首先是字符串)。

【讨论】:

  • 我真的怀疑它是否
  • @Andrey:它应该具有线性运行时间,并且只构造一次数组。常见的正则表达式问题涉及非线性运行时间,常见的字符串替换问题涉及重复复制字符串。与带字符串替换的正则表达式相比,为什么这个解决方案不快?我唯一能想到的就是函数调用开销。没有分析两者,这是猜测。
  • @digEmAll,是的,我会修复它:) 有趣的错误。
  • @Andrey:是的,它真的很快。唯一的小问题是它需要通过一个一次性数组。
  • 正如在别处提到的,x => !Char.IsWhiteSpace(x) 是首选。这个 linq 命令是我为类似问题选择的解决方案。谢谢!
【解决方案4】:

你应该试试String.Trim()。它将修剪字符串从头到尾的所有空格

或者您可以从链接的主题中尝试此方法:[link]

    public static unsafe string StripTabsAndNewlines(string s)
    {
        int len = s.Length;
        char* newChars = stackalloc char[len];
        char* currentChar = newChars;

        for (int i = 0; i < len; ++i)
        {
            char c = s[i];
            switch (c)
            {
                case '\r':
                case '\n':
                case '\t':
                    continue;
                default:
                    *currentChar++ = c;
                    break;
            }
        }
        return new string(newChars, 0, (int)(currentChar - newChars));
    }

【讨论】:

  • 好吧,你应该有非常严肃的理由在安全代码中引入不安全代码。清洁绳绝对不是那个。
  • 我认为 4-5 分钟来执行一个简单的动作 - 是不可接受的。它可以更快。
  • 不需要使用指针,Char.IsWhiteSpace(c) 也可以代替 switch 是更好的解决方案。
【解决方案5】:
emailaddress.Replace("  ", string.Empty);

【讨论】:

    【解决方案6】:

    有许多不同的方法,有些比其他更快:

    public static string StripTabsAndNewlines(this string str) {
    
        //string builder (fast)
        StringBuilder sb = new StringBuilder(str.Length);
        for (int i = 0; i < str.Length; i++) {
            if ( !  Char.IsWhiteSpace(s[i])) {
                sb.Append();
            }
        }
        return sb.tostring();
    
        //linq (faster ?)
        return new string(str.ToCharArray().Where(c => !Char.IsWhiteSpace(c)).ToArray());
    
        //regex (slow)
        return Regex.Replace(str, @"\s+", "")
    
    }
    

    【讨论】:

      【解决方案7】:

      请使用String 类的TrimEnd() 方法。你可以找到一个很好的例子here.

      【讨论】:

      • String 类的 Trim* 方法只修剪开头或结尾
      【解决方案8】:

      您应该考虑在存储过程中替换记录集上的空格,或者尽可能使用REPLACE( ) 函数进行查询,甚至更好地修复您的数据库记录,因为电子邮件地址中的空格无论如何都是无效的。

      正如其他人所提到的,您需要分析不同的方法。如果您使用正则表达式,则应至少将其设为类级静态变量:

      public static Regex MultipleSpaces = new Regex(@"\s+", RegexOptions.Compiled);
      

      emailAddress.Where(x=&gt;{ return x != ' ';}).ToString( ) 可能有函数开销,尽管它可以被 Microsoft 优化为内联 - 再次分析会给你答案。

      最有效的方法是分配一个缓冲区并将一个字符一个字符地复制到一个新的缓冲区,并在执行此操作时跳过空格。 C# 确实支持指针,因此您可以使用不安全的代码、分配原始缓冲区并使用指针算术来复制,就像在 C 中一样,这是尽可能快的。 SQL 中的REPLACE( ) 将为您处理它。

      【讨论】:

        【解决方案9】:
        string str = "Hi!! this is a bunch of text with spaces";
        
        MessageBox.Show(new String(str.Where(c => c != ' ').ToArray()));
        

        【讨论】:

          【解决方案10】:

          我没有对此进行性能测试,但它比大多数其他答案更简单。

          var s1 = "\tstring \r with \t\t  \nwhitespace\r\n";
          var s2 = string.Join("", s1.Split());
          

          结果是

          stringwithwhitespace
          

          【讨论】:

            【解决方案11】:
            string input =Yourinputstring;
            string[] strings = input.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string value in strings)
            {
               string newv= value.Trim();
               if (newv.Length > 0)
               newline += value + "\r\n";
            }
            

            【讨论】:

              【解决方案12】:
              string s = " Your Text ";
              
              string new = s.Replace(" ", string.empty);
              
              // Output:
              // "YourText"
              

              【讨论】:

                【解决方案13】:

                执行此操作的最快和通用方法(也将处理行终止符、制表符)。解决这个问题并不需要 Regex 强大的工具,但 Regex 会降低性能。

                new string
                    (stringToRemoveWhiteSpaces
                       .Where
                       (
                         c => !char.IsWhiteSpace(c)
                       )
                       .ToArray<char>()
                    )
                

                【讨论】:

                  猜你喜欢
                  • 2015-06-19
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-03-14
                  • 2012-02-02
                  • 2012-04-25
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-11-15
                  相关资源
                  最近更新 更多