Вопрос по c#, string, whitespace – Как заменить несколько пробелов одним пробелом

99

Допустим, у меня есть строка, такая как:

"Hello     how are   you           doing?"

Я хотел бы функцию, которая превращает несколько пробелов в один пробел.

Так что я бы получил:

"Hello how are you doing?"

Я знаю, что мог бы использовать регулярное выражение или позвонить

string s = "Hello     how are   you           doing?".replace("  "," ");

Но мне придется вызывать его несколько раз, чтобы все последовательные пробелы были заменены только одним.

Уже есть встроенный метод для этого?

Возможный дубликатstackoverflow.com/questions/206717/… Michael Freidgeim
И хотите ли вы, чтобы какие-либо непробельные пробелы были преобразованы в пробелы? Jon Skeet
Не могли бы вы уточнить: вы имеете дело только с пробелами или "все" пробельные? Jon Skeet
Я просто имел в виду, что все пробелы в серии должны быть не более 1 Matt

Ваш Ответ

13   ответов
1
Regex regex = new Regex(@"\W+");
string outputString = regex.Replace(inputString, " ");
Это заменяет все несловарные символы пробелом. Так что это также заменит такие вещи, как скобки, кавычки и т. Д., Что может оказаться не тем, что вы хотите.
4

это легко сделать с помощью регулярного выражения. Я просто добавлю, что вы можете добавить к нему .trim (), чтобы избавиться от пробелов в начале / конце.

16

улярное выражение правильным образом, вам не понадобятся множественные вызовы.

Измените это на это:

string s = System.Text.RegularExpressions.Regex.Replace(s, @"\s{2,}", " "); 
Моя единственная проблема с@"\s{2,}" является то, что он не может заменить одиночные вкладки и другие символы пробела Unicode с пробелом. Если вы собираетесь заменить 2 вкладки пробелом, то вам, вероятно, следует заменить 1 вкладку пробелом.@"\s+" сделаю это для вас.
Этот ответ должен быть наверху, мне потребовалось 10 секунд, чтобы найти самый полезный ответ
178
string cleanedString = System.Text.RegularExpressions.Regex.Replace(dirtyString,@"\s+"," ");
Если вы не используете "{2,}" вместо "+" избежать замены одиночных пробелов?
хороший улов, если вы просто хотите, чтобы пробелы переключали шаблон на «[] +»
IMO, избегая регулярных выражений, если вам удобно с ними преждевременной оптимизации
Если ваше приложение не критично ко времени, оно может позволить себе потратить 1 микросекунду на обработку.
Обратите внимание, что \ s; заменяет не только пробелы, но и символы новой строки.
2

Linha.Split(" ").ToList().Where(Function(x) x <> " ").ToArray

C #

Linha.Split(" ").ToList().Where(x => x != " ").ToArray();

Наслаждайтесь силой LINQ = D

Именно так! Для меня это тоже самый элегантный подход. Итак, для записи, в C # это будет:string.Join(" ", myString.Split(' ').Where(s => s != " ").ToArray())
Незначительное улучшениеSplit чтобы поймать все пробелы и удалитьWhere пункт:myString.Split(null as char[], StringSplitOptions.RemoveEmptyEntries)
18

я хотел бы указать на один подход, которыйdoesn't Работа:

public static string DontUseThisToCollapseSpaces(string text)
{
    while (text.IndexOf("  ") != -1)
    {
        text = text.Replace("  ", " ");
    }
    return text;
}

Это может зациклить навсегда. Кто-нибудь хочет догадаться, почему? (Я только сталкивался с этим, когда он был задан как вопрос группы новостей несколько лет назад ... кто-то фактически столкнулся с этим как проблема.)

Это связано с тем, что IndexOf игнорирует некоторые символы Юникода, в этом случае конкретным виновником является азиатский символ iirc. Хм, нулевой ширины, по данным Google.
И Хоукер получает приз :)
Я думаю, что я помню этот вопрос, заданный некоторое время назад на SO. IndexOf игнорирует определенные символы, которые Replace не использует. Таким образом, двойное пространство всегда было, просто никогда не удалялось.
Я узнал, что трудный путь :(stackoverflow.com/questions/9260693/…
4

public static string TrimWhiteSpace(this string Value)
{
    StringBuilder sbOut = new StringBuilder();
    if (!string.IsNullOrEmpty(Value))
    {
        bool IsWhiteSpace = false;
        for (int i = 0; i < Value.Length; i++)
        {
            if (char.IsWhiteSpace(Value[i])) //Comparion with WhiteSpace
            {
                if (!IsWhiteSpace) //Comparison with previous Char
                {
                    sbOut.Append(Value[i]);
                    IsWhiteSpace = true;
                }
            }
            else
            {
                IsWhiteSpace = false;
                sbOut.Append(Value[i]);
            }
        }
    }
    return sbOut.ToString();
}

так что вы можете:

string cleanedString = dirtyString.TrimWhiteSpace();
3

что я использую, потому что кажется, что я придумал что-то другое. Я использовал это некоторое время, и это достаточно быстро для меня. Я не уверен, как это складывается с остальными. Я использую его в средстве записи файлов с разделителями и запускаю через него большие таблицы данных по одному полю за раз.

    public static string NormalizeWhiteSpace(string S)
    {
        string s = S.Trim();
        bool iswhite = false;
        int iwhite;
        int sLength = s.Length;
        StringBuilder sb = new StringBuilder(sLength);
        foreach(char c in s.ToCharArray())
        {
            if(Char.IsWhiteSpace(c))
            {
                if (iswhite)
                {
                    //Continuing whitespace ignore it.
                    continue;
                }
                else
                {
                    //New WhiteSpace

                    //Replace whitespace with a single space.
                    sb.Append(" ");
                    //Set iswhite to True and any following whitespace will be ignored
                    iswhite = true;
                }  
            }
            else
            {
                sb.Append(c.ToString());
                //reset iswhitespace to false
                iswhite = false;
            }
        }
        return sb.ToString();
    }
-1

private static readonly char[] whitespace = new char[] { ' ', '\n', '\t', '\r', '\f', '\v' };
public static string Normalize(string source)
{
   return String.Join(" ", source.Split(whitespace, StringSplitOptions.RemoveEmptyEntries));
}

Это удалит начальные и конечные пробелы, а также свернет все внутренние пробелы в один символ пробела. Если вы действительно хотите свернуть пробелы, то решения, использующие регулярные выражения, лучше; в противном случае это решение лучше. (См.анализ сделано Джоном Скитом.)

пробел здесь не объявлен
Говоря о накладных расходах, почему ты звонишь?source.ToCharArray() а потом выбрасывать результат?
Если регулярное выражение скомпилировано и кэшировано, я не уверен, что он имеет больше накладных расходов, чем разделение и объединение, что может создатьloads промежуточных строк мусора. Вы сделали тщательные тесты обоих подходов, прежде чем предположить, что ваш путь быстрее?
And призваниеToCharArray() на результат string.Join, только для создания новой строки ... вау, для того, чтобы быть в посте жалобы на накладные расходы просто замечательно. -1.
Ох, и предполагаяwhitespace являетсяnew char[] { ' ' }, это даст неправильный результат, если строка ввода начинается или заканчивается пробелом.
2

которую выложил Джон Скит, я попытался выяснить, смогу ли я сделать цикл, написанный от руки, быстрее.
Я могу побить NormalizeWithSplitAndJoin каждый раз, но побью только NormalizeWithRegex с входами 1000, 5.

static string NormalizeWithLoop(string input)
{
    StringBuilder output = new StringBuilder(input.Length);

    char lastChar = '*';  // anything other then space 
    for (int i = 0; i < input.Length; i++)
    {
        char thisChar = input[i];
        if (!(lastChar == ' ' && thisChar == ' '))
            output.Append(thisChar);

        lastChar = thisChar;
    }

    return output.ToString();
}

Я не смотрел на машинный код, который генерирует джиттер, однако я ожидаю, что проблема заключается во времени, затрачиваемом на вызов StringBuilder.Append (), и для более эффективной работы потребуется использование небезопасного кода.

So Regex.Replace() is very fast and hard to beat!!

53

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

Существует разница между "пробелом" и "пробел". если тыonly означает пробелы, то вы должны использовать регулярное выражение" {2,}", Если ты имеешь ввидуany пробелы, это другое дело. Долженall пробелы будут преобразованы в пробелы? Что должно случиться с космосом в начале и в конце?

Для приведенного ниже теста я предположил, что вы заботитесь только о пробелах, и вы не хотите ничего делать с отдельными пробелами, даже в начале и в конце.

Обратите внимание, что правильность почти всегда важнее, чем производительность. Тот факт, что решение Split / Join удаляет любые начальные / конечные пробелы (даже только одиночные пробелы), является неверным, поскольку ваши указанные требования (которые могут быть неполными, конечно).

Тест используетMiniBench.

using System;
using System.Text.RegularExpressions;
using MiniBench;

internal class Program
{
    public static void Main(string[] args)
    {

        int size = int.Parse(args[0]);
        int gapBetweenExtraSpaces = int.Parse(args[1]);

        char[] chars = new char[size];
        for (int i=0; i < size/2; i += 2)
        {
            // Make sure there actually *is* something to do
            chars[i*2] = (i % gapBetweenExtraSpaces == 1) ? ' ' : 'x';
            chars[i*2 + 1] = ' ';
        }
        // Just to make sure we don't have a \0 at the end
        // for odd sizes
        chars[chars.Length-1] = 'y';

        string bigString = new string(chars);
        // Assume that one form works :)
        string normalized = NormalizeWithSplitAndJoin(bigString);


        var suite = new TestSuite<string, string>("Normalize")
            .Plus(NormalizeWithSplitAndJoin)
            .Plus(NormalizeWithRegex)
            .RunTests(bigString, normalized);

        suite.Display(ResultColumns.All, suite.FindBest());
    }

    private static readonly Regex MultipleSpaces = 
        new Regex(@" {2,}", RegexOptions.Compiled);

    static string NormalizeWithRegex(string input)
    {
        return MultipleSpaces.Replace(input, " ");
    }

    // Guessing as the post doesn't specify what to use
    private static readonly char[] Whitespace =
        new char[] { ' ' };

    static string NormalizeWithSplitAndJoin(string input)
    {
        string[] split = input.Split
            (Whitespace, StringSplitOptions.RemoveEmptyEntries);
        return string.Join(" ", split);
    }
}

Несколько тестовых прогонов:

c:\Users\Jon\Test>test 1000 50
============ Normalize ============
NormalizeWithSplitAndJoin  1159091 0:30.258 22.93
NormalizeWithRegex        26378882 0:30.025  1.00

c:\Users\Jon\Test>test 1000 5
============ Normalize ============
NormalizeWithSplitAndJoin  947540 0:30.013 1.07
NormalizeWithRegex        1003862 0:29.610 1.00


c:\Users\Jon\Test>test 1000 1001
============ Normalize ============
NormalizeWithSplitAndJoin  1156299 0:29.898 21.99
NormalizeWithRegex        23243802 0:27.335  1.00

Здесь первое число - это количество итераций, второе - время, затрачиваемое на третье, и третье - это масштабированная оценка, где 1,0 является лучшим.

Это показывает, что по крайней мере в некоторых случаях (включая этот) регулярное выражениеcan опередить решение Split / Join, иногда с очень значительным преимуществом.

Однако, если вы переключитесь на «все пробелы» требование, затем разделить / присоединитьсяdoes Похоже, чтобы выиграть. Как это часто бывает, дьявол кроется в деталях ...

Отличный анализ. Похоже, что мы оба были правы в разной степени. Код в моем ответе был взят из более крупной функции, которая способна нормализовать все пробельные символы и / или управляющие символы внутри строки, а также с начала и до конца.
@IanRingrose Какой мусор можно создать?
NormalizeWithSplitAndJoin создаст намного больше мусора, трудно сказать, будет ли реальная проблема попадать больше времени GC, чем отметка.
Используя только те пробельные символы, которые вы указали, в большинстве моих тестов регулярные выражения и Split / Join были примерно равны - S / J имел крошечное, крошечное преимущество за счет правильности и сложности. По этим причинам я обычно предпочитаю регулярное выражение. Не поймите меня неправильно - я далеко не фанат регулярных выражений, но мне не нравится писать более сложный код для повышения производительности без реального тестирования производительности в первую очередь.
0

var regExp = / \ s + / g, newString = oldString.replace (regExp, '' ');

2

A fast extra whitespace remover... Это самый быстрый способ, основанный на действующей копии Фелипе Мачадо.

{
    var len = str.Length;
    var src = str.ToCharArray();
    int dstIdx = 0;
    bool lastWasWS = false;
    for (int i = 0; i < len; i++)
    {
        var ch = src[i];
        if (src[i] == '\u0020')
        {
            if (lastWasWS == false)
            {
                src[dstIdx++] = ch;
                lastWasWS = true;
            }
        }
        else
        { 
            lastWasWS = false;
            src[dstIdx++] = ch;
        }
    }
    return new string(src, 0, dstIdx);
}

The benchmarks...

InPlaceCharArraySpaceOnly byФелипе Мачадо на CodeProject 2015 и доработанный Sunsetquest для удаления из нескольких пространств. Time: 3.75 Ticks

InPlaceCharArray byФелипе Мачадо 2015 и слегка доработанный Sunsetquest для удаления из нескольких пространств. Time 6.50 Ticks  (поддерживает также вкладки)

SplitAndJoinOnSpace byДжон Скит. Time: 13.25 Ticks

StringBuilder отFubo Time: 13.5 Ticks (поддерживает также вкладки)

Regex с компиляцией поДжон Скит. Time: 17 Ticks

StringBuilder отДэвид С 2013 Time: 30.5 Ticks

Regex с некомпиляцией поBrandon Time: 63.25 Ticks

StringBuilder отuser214147 Time: 77.125 Ticks

Regex с некомпиляциейТим Хулихан Time: 147.25 Ticks

The Benchmark code...

using System;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.Threading;
using System.Text;

static class Program
{
    public static void Main(string[] args)
    {
    long seed = ConfigProgramForBenchmarking();

    Stopwatch sw = new Stopwatch();

    string warmup = "This is   a Warm  up function for best   benchmark results." + seed;
    string input1 = "Hello World,    how are   you           doing?" + seed;
    string input2 = "It\twas\t \tso    nice  to\t\t see you \tin 1950.  \t" + seed;
    string correctOutput1 = "Hello World, how are you doing?" + seed;
    string correctOutput2 = "It\twas\tso nice to\tsee you in 1950. " + seed;
    string output1,output2;

    //warm-up timer function
    sw.Restart();
    sw.Stop();

    sw.Restart();
    sw.Stop();
    long baseVal = sw.ElapsedTicks;

    // InPlace Replace by Felipe Machado but modified by Ryan for multi-space removal (http://www.codeproject.com/Articles/1014073/Fastest-method-to-remove-all-whitespace-from-Strin)
    output1 = InPlaceCharArraySpaceOnly (warmup);
    sw.Restart();
    output1 = InPlaceCharArraySpaceOnly (input1);
    output2 = InPlaceCharArraySpaceOnly (input2);
    sw.Stop();
    Console.WriteLine("InPlaceCharArraySpaceOnly : " + (sw.ElapsedTicks - baseVal));
    Console.WriteLine("  Trial1:(spaces only) " + (output1 == correctOutput1 ? "PASS " : "FAIL "));
    Console.WriteLine("  Trial2:(spaces+tabs) " + (output2 == correctOutput2 ? "PASS " : "FAIL "));

    // InPlace Replace by Felipe R. Machado and slightly modified by Ryan for multi-space removal (http://www.codeproject.com/Articles/1014073/Fastest-method-to-remove-all-whitespace-from-Strin)
    output1 = InPlaceCharArray(warmup);
    sw.Restart();
    output1 = InPlaceCharArray(input1);
    output2 = InPlaceCharArray(input2);
    sw.Stop();
    Console.WriteLine("InPlaceCharArray: " + (sw.ElapsedTicks - baseVal));
    Console.WriteLine("  Trial1:(spaces only) " + (output1 == correctOutput1 ? "PASS " : "FAIL "));
    Console.WriteLine("  Trial2:(spaces+tabs) " + (output2 == correctOutput2 ? "PASS " : "FAIL "));

    //Regex with non-compile Tim Hoolihan (https://stackoverflow.com/a/1279874/2352507)
    string cleanedString = 
    output1 = Regex.Replace(warmup, @"\s+", " ");
    sw.Restart();
    output1 = Regex.Replace(input1, @"\s+", " ");
    output2 = Regex.Replace(input2, @"\s+", " ");
    sw.Stop();
    Console.WriteLine("Regex by Tim Hoolihan: " + (sw.ElapsedTicks - baseVal));
    Console.WriteLine("  Trial1:(spaces only) " + (output1 == correctOutput1 ? "PASS " : "FAIL "));
    Console.WriteLine("  Trial2:(spaces+tabs) " + (output2 == correctOutput2 ? "PASS " : "FAIL "));

    //Regex with compile by Jon Skeet (https://stackoverflow.com/a/1280227/2352507)
    output1 = MultipleSpaces.Replace(warmup, " ");
    sw.Restart();
    output1 = MultipleSpaces.Replace(input1, " ");
    output2 = MultipleSpaces.Replace(input2, " ");
    sw.Stop();
    Console.WriteLine("Regex with compile by Jon Skeet: " + (sw.ElapsedTicks - baseVal));
    Console.WriteLine("  Trial1:(spaces only) " + (output1 == correctOutput1 ? "PASS " : "FAIL "));
    Console.WriteLine("  Trial2:(spaces+tabs) " + (output2 == correctOutput2 ? "PASS " : "FAIL "));

    //Split And Join by Jon Skeet (https://stackoverflow.com/a/1280227/2352507)
    output1 = SplitAndJoinOnSpace(warmup);
    sw.Restart();
    output1 = SplitAndJoinOnSpace(input1);
    output2 = SplitAndJoinOnSpace(input2);
    sw.Stop();
    Console.WriteLine("Split And Join by Jon Skeet: " + (sw.ElapsedTicks - baseVal));
    Console.WriteLine("  Trial1:(spaces only) " + (output1 == correctOutput1 ? "PASS " : "FAIL "));
    Console.WriteLine("  Trial2:(spaces+tabs) " + (output2 == correctOutput2 ? "PASS " : "FAIL "));

    //Regex by Brandon (https://stackoverflow.com/a/1279878/2352507
    output1 = Regex.Replace(warmup, @"\s{2,}", " ");
    sw.Restart();
    output1 = Regex.Replace(input1, @"\s{2,}", " ");
    output2 = Regex.Replace(input2, @"\s{2,}", " ");
    sw.Stop();
    Console.WriteLine("Regex by Brandon: " + (sw.ElapsedTicks - baseVal));
    Console.WriteLine("  Trial1:(spaces only) " + (output1 == correctOutput1 ? "PASS " : "FAIL "));
    Console.WriteLine("  Trial2:(spaces+tabs) " + (output2 == correctOutput2 ? "PASS " : "FAIL "));

    //StringBuilder by user214147 (https://stackoverflow.com/a/2156660/2352507
    output1 = user214147(warmup);
    sw.Restart();
    output1 = user214147(input1);
    output2 = user214147(input2);
    sw.Stop();
    Console.WriteLine("StringBuilder by user214147: " + (sw.ElapsedTicks - baseVal));
    Console.WriteLine("  Trial1:(spaces only) " + (output1 == correctOutput1 ? "PASS " : "FAIL "));
    Console.WriteLine("  Trial2:(spaces+tabs) " + (output2 == correctOutput2 ? "PASS " : "FAIL "));

    //StringBuilder by fubo (https://stackoverflow.com/a/27502353/2352507
    output1 = fubo(warmup);
    sw.Restart();
    output1 = fubo(input1);
    output2 = fubo(input2);
    sw.Stop();
    Console.WriteLine("StringBuilder by fubo: " + (sw.ElapsedTicks - baseVal));
    Console.WriteLine("  Trial1:(spaces only) " + (output1 == correctOutput1 ? "PASS " : "FAIL "));
    Console.WriteLine("  Trial2:(spaces+tabs) " + (output2 == correctOutput2 ? "PASS " : "FAIL "));


    //StringBuilder by David S 2013 (https://stackoverflow.com/a/16035044/2352507)
    output1 = SingleSpacedTrim(warmup);
    sw.Restart();
    output1 = SingleSpacedTrim(input1);
    output2 = SingleSpacedTrim(input2);
    sw.Stop();
    Console.WriteLine("StringBuilder(SingleSpacedTrim) by David S: " + (sw.ElapsedTicks - baseVal));
    Console.WriteLine("  Trial1:(spaces only) " + (output1 == correctOutput1 ? "PASS " : "FAIL "));
    Console.WriteLine("  Trial2:(spaces+tabs) " + (output2 == correctOutput2 ? "PASS " : "FAIL "));
}

// InPlace Replace by Felipe Machado and slightly modified by Ryan for multi-space removal (http://www.codeproject.com/Articles/1014073/Fastest-method-to-remove-all-whitespace-from-Strin)

{
    var len = str.Length;
    var src = str.ToCharArray();
    int dstIdx = 0;
    bool lastWasWS = false;
    for (int i = 0; i < len; i++)
    {
        var ch = src[i];
        if (src[i] == '\u0020')
        {
            if (lastWasWS == false)
            {
                src[dstIdx++] = ch;
                lastWasWS = true;
            }
        }
        else
        { 
            lastWasWS = false;
            src[dstIdx++] = ch;
        }
    }
    return new string(src, 0, dstIdx);
}

// InPlace Replace by Felipe R. Machado but modified by Ryan for multi-space removal (http://www.codeproject.com/Articles/1014073/Fastest-method-to-remove-all-whitespace-from-Strin)
static string InPlaceCharArraySpaceOnly (string str)
{
    var len = str.Length;
    var src = str.ToCharArray();
    int dstIdx = 0;
    bool lastWasWS = false; //Added line
    for (int i = 0; i < len; i++)
    {
        var ch = src[i];
        switch (ch)
        {
            case '\u0020': //SPACE
            case '\u00A0': //NO-BREAK SPACE
            case '\u1680': //OGHAM SPACE MARK
            case '\u2000': // EN QUAD
            case '\u2001': //EM QUAD
            case '\u2002': //EN SPACE
            case '\u2003': //EM SPACE
            case '\u2004': //THREE-PER-EM SPACE
            case '\u2005': //FOUR-PER-EM SPACE
            case '\u2006': //SIX-PER-EM SPACE
            case '\u2007': //FIGURE SPACE
            case '\u2008': //PUNCTUATION SPACE
            case '\u2009': //THIN SPACE
            case '\u200A': //HAIR SPACE
            case '\u202F': //NARROW NO-BREAK SPACE
            case '\u205F': //MEDIUM MATHEMATICAL SPACE
            case '\u3000': //IDEOGRAPHIC SPACE
            case '\u2028': //LINE SEPARATOR
            case '\u2029': //PARAGRAPH SEPARATOR
            case '\u0009': //[ASCII Tab]
            case '\u000A': //[ASCII Line Feed]
            case '\u000B': //[ASCII Vertical Tab]
            case '\u000C': //[ASCII Form Feed]
            case '\u000D': //[ASCII Carriage Return]
            case '\u0085': //NEXT LINE
                if (lastWasWS == false) //Added line
                {
                    src[dstIdx++] = ch; //Added line
                    lastWasWS = true; //Added line
                }
            continue;
            default:
                lastWasWS = false; //Added line 
                src[dstIdx++] = ch;
                break;
        }
    }
    return new string(src, 0, dstIdx);
}

static readonly Regex MultipleSpaces =
    new Regex(@" {2,}", RegexOptions.Compiled);

//Split And Join by Jon Skeet (https://stackoverflow.com/a/1280227/2352507)
static string SplitAndJoinOnSpace(string input)
{
    string[] split = input.Split(new char[] { ' '}, StringSplitOptions.RemoveEmptyEntries);
    return string.Join(" ", split);
}

//StringBuilder by user214147 (https://stackoverflow.com/a/2156660/2352507
public static string user214147(string S)
{
    string s = S.Trim();
    bool iswhite = false;
    int iwhite;
    int sLength = s.Length;
    StringBuilder sb = new StringBuilder(sLength);
    foreach (char c in s.ToCharArray())
    {
        if (Char.IsWhiteSpace(c))
        {
            if (iswhite)
            {
                //Continuing whitespace ignore it.
                continue;
            }
            else
            {
                //New WhiteSpace

                //Replace whitespace with a single space.
                sb.Append(" ");
                //Set iswhite to True and any following whitespace will be ignored
                iswhite = true;
            }
        }
        else
        {
            sb.Append(c.ToString());
            //reset iswhitespace to false
            iswhite = false;
        }
    }
    return sb.ToString();
}

//StringBuilder by fubo (https://stackoverflow.com/a/27502353/2352507
public static string fubo(this string Value)
{
    StringBuilder sbOut = new StringBuilder();
    if (!string.IsNullOrEmpty(Value))
    {
        bool IsWhiteSpace = false;
        for (int i = 0; i < Value.Length; i++)
        {
            if (char.IsWhiteSpace(Value[i])) //Comparison with WhiteSpace
            {
                if (!IsWhiteSpace) //Comparison with previous Char
                {
                    sbOut.Append(Value[i]);
                    IsWhiteSpace = true;
                }
            }
            else
            {
                IsWhiteSpace = false;
                sbOut.Append(Value[i]);
            }
        }
    }
    return sbOut.ToString();
}

//David S. 2013 (https://stackoverflow.com/a/16035044/2352507)
public static String SingleSpacedTrim(String inString)
{
    StringBuilder sb = new StringBuilder();
    Boolean inBlanks = false;
    foreach (Char c in inString)
    {
        switch (c)
        {
            case '\r':
            case '\n':
            case '\t':
            case ' ':
                if (!inBlanks)
                {
                    inBlanks = true;
                    sb.Append(' ');
                }
                continue;
            default:
                inBlanks = false;
                sb.Append(c);
                break;
        }
    }
    return sb.ToString().Trim();
}

/// <summary>
/// We want to run this item with max priory to lower the odds of
/// the OS from doing program context switches in the middle of our code. 
/// source:https://stackoverflow.com/a/16157458 
/// </summary>
/// <returns>random seed</returns>
private static long ConfigProgramForBenchmarking()
{
    //prevent the JIT Compiler from optimizing Fkt calls away
    long seed = Environment.TickCount;
    //use the second Core/Processor for the test
    Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(2);
    //prevent "Normal" Processes from interrupting Threads
    Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
    //prevent "Normal" Threads from interrupting this thread
    Thread.CurrentThread.Priority = ThreadPriority.Highest;
    return seed;
}

}

Benchmark notes: Release Mode, no-debugger attached, i7 processor, avg of 4 runs, only short strings tested

Похожие вопросы