Самый быстрый способ удалить символы из строки - PullRequest
21 голосов
/ 02 февраля 2010

У меня есть строка, из которой я должен удалить следующие символы: '\ r', '\ n' и '\ t'. Я пробовал три разных способа удаления этих символов и сравнивал их, чтобы получить самое быстрое решение.

Ниже приведены методы и время выполнения, когда я запускал их 1000000 раз:

Это должно быть самое быстрое решение, если мне нужно удалить 1 или 2 символа. Но когда я добавляю больше символов, это начинает занимать больше времени

str = str.Replace("\r", string.Empty).Replace("\n", string.Empty).Replace("\t", string.Empty);

Время выполнения = 1695

Для 1 или 2 символов он был медленнее, чем String.Replace, но для 3 символов он показал лучшую производительность.

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

Время выполнения = 1030

Самый медленный из всех, даже с 1 символом. Может быть, мое регулярное выражение не самое лучшее.

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

Время выполнения = 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();

Ответы [ 7 ]

17 голосов
/ 02 февраля 2010

Вот сверхбыстрая небезопасная версия, версия 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));
    }

А вот и тесты (время обрезки 1000000 строк в мс)

    cornerback84's String.Replace:         9433
    Andy West's String.Concat:             4756
    AviJ's char array:                     1374
    Matt Howells' char pointers:           1163
9 голосов
/ 02 февраля 2010

Я полагаю, что вы получите наилучшую возможную производительность, составив новую строку в виде массива 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);

РЕДАКТИРОВАТЬ: с использованием String (s2, 0, i2) вместо Trim (), за предложение

4 голосов
/ 02 февраля 2010
String.Join(null, str.Split(new char[] { '\t', '\r', '\n' },
    StringSplitOptions.None));

может дать вам повышение производительности по сравнению с Aggregate(), поскольку Join() предназначен для строк.

EDIT

На самом деле, это может быть даже лучше:

String.Concat(str.Split(new char[] { '\t', '\r', '\n' },
    StringSplitOptions.None));
2 голосов
/ 25 ноября 2012

Еще быстрее:

public static string RemoveMultipleWhiteSpaces(string s)
    {
        char[] sResultChars = new char[s.Length];

        bool isWhiteSpace = false;
        int sResultCharsIndex = 0;

        for (int i = 0; i < s.Length; i++)
        {
            if (s[i] == ' ')
            {
                if (!isWhiteSpace)
                {
                    sResultChars[sResultCharsIndex] = s[i];
                    sResultCharsIndex++;
                    isWhiteSpace = true;
                }
            }
            else
            {
                sResultChars[sResultCharsIndex] = s[i];
                sResultCharsIndex++;
                isWhiteSpace = false;
            }
        }

        return new string(sResultChars, 0, sResultCharsIndex);
    }
2 голосов
/ 02 февраля 2010

Зацикливание строки и использование (только одного) StringBuilder (с правильным аргументом конструктора, чтобы избежать ненужных выделений памяти) для создания новой строки может быть быстрее.

1 голос
/ 02 февраля 2010

попробуйте

string str = "something \tis \nbetter than nothing";
string removeChars = new String(new Char[]{'\n', '\t'});
string newStr = new string(str.ToCharArray().Where(c => !removeChars.Contains(c)).ToArray());
0 голосов
/ 04 мая 2012
string str;
str = str.Replace(Environment.NewLine, string.Empty).Replace("\t", string.Empty);
...