从字符串中删除字符的最快方法

ata*_*ata 21 .net c# string

我有一个字符串,我必须从中删除以下字符:'\ r','\n'和'\ t'.我尝试了三种不同的方法来删除这些字符并对它们进行基准测试,以便我可以获得最快的解决方案.

以下是我运行1000000次的方法和执行时间:

如果我要删除1或2个字符,它应该是最快的解决方案.但随着我投入更多的焦炭,它开始需要更多的时间

str = str.Replace("\r", string.Empty).Replace("\n", string.Empty).Replace("\t", string.Empty);
Run Code Online (Sandbox Code Playgroud)

执行时间= 1695

对于1或2个char,这比String.Replace慢,但是对于3个char它表现出更好的性能.

string[] split = str.Split(new char[] { '\t', '\r', '\n' }, StringSplitOptions.None);
str = split.Aggregate<string>((str1, str2) => str1 + str2);
Run Code Online (Sandbox Code Playgroud)

执行时间= 1030

最慢的,即使是1个字符.也许我的正则表达不是最好的.

str = Regex.Replace(str, "[\r\n\t]", string.Empty, RegexOptions.Compiled);
Run Code Online (Sandbox Code Playgroud)

执行时间= 3500

这些是我提出的三种解决方案.有没有更好更快的解决方案,这里的任何人都知道,或者我可以在此代码中做任何改进?

我用于基准测试的字符串:

StringBuilder builder = new StringBuilder();
        builder.AppendFormat("{0}\r\n{1}\t\t\t\r\n{2}\t\r\n{3}\r\n{4}\t\t\r\n{5}\r\n{6}\r\n{7}\r\n{8}\r\n{9}",
         "SELECT ",
         "[Extent1].[CustomerID] AS [CustomerID], ",
         "[Extent1].[NameStyle] AS [NameStyle], ",
         "[Extent1].[Title] AS [Title], ",
           "[Extent1].[FirstName] AS [FirstName], ",
           "[Extent1].[MiddleName] AS [MiddleName], ",
           "[Extent1].[LastName] AS [LastName], ",
           "[Extent1].[Suffix] AS [Suffix], ",
           "[Extent1].[CompanyName] AS [CompanyName], ",
           "[Extent1].[SalesPerson] AS [SalesPerson], ");
        string str = builder.ToString();
Run Code Online (Sandbox Code Playgroud)

Mat*_*lls 17

这是超快速的不安全版本,版本2.

    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));
    }
Run Code Online (Sandbox Code Playgroud)

以下是基准测试(以ms为单位剥离1000000个字符串的时间)

    cornerback84's String.Replace:         9433
    Andy West's String.Concat:             4756
    AviJ's char array:                     1374
    Matt Howells' char pointers:           1163

  • 顺便说一句,你需要一台新机器:P (5认同)
  • 是的。执行时间 = 195 (2认同)
  • 这是最近的 Xeon - 可能我们的基准测试设置不同。 (2认同)

Avi*_*viJ 9

我相信通过将新字符串组合为char数组并在完成后将其转换为字符串,您将获得最佳性能,如下所示:

string s = "abc";
int len = s.Length;
char[] s2 = new char[len];
int i2 = 0;
for (int i = 0; i < len; i++)
{
    char c = s[i];
    if (c != '\r' && c != '\n' && c != '\t')
        s2[i2++] = c;
}
return new String(s2, 0, i2);
Run Code Online (Sandbox Code Playgroud)

编辑:根据建议使用String(s2,0,i2)而不是Trim()

  • 事实上我做了一点修改.你已经保持了新数组的长度,即i2.所以不是修剪,你可以使用return new String(s2,0,i2); 这使执行时间达到255 (2认同)

And*_*est 6

String.Join(null, str.Split(new char[] { '\t', '\r', '\n' },
    StringSplitOptions.None));
Run Code Online (Sandbox Code Playgroud)

Aggregate()由于Join()是为字符串设计的,因此可能会比使用提高性能。

编辑

实际上,这可能会更好:

String.Concat(str.Split(new char[] { '\t', '\r', '\n' },
    StringSplitOptions.None));
Run Code Online (Sandbox Code Playgroud)