Возвращайте одинаковые пробелы между словами, используя C # [duplicate]

select * from yourtable
group by id
having rev=max(rev);
33
задан Navid Rahmani 14 July 2011 в 09:40
поделиться

23 ответа

Самый быстрый способ? Итерации по строке и построение второй копии в символе StringBuilder по символу, только копирование одного пробела для каждой группы пробелов.

. Более простые для ввода Replace варианты создадут загрузку лишнего (или время траты, создающее регулярное выражение DFA).

Редактировать с помощью результатов сравнения:

Используя http://ideone.com/h6pw3 , с n = 50 (пришлось уменьшить его на идеон, потому что потребовалось так много времени, чтобы убить мой процесс), я получаю:

Regex: 7771ms.

Stringbuilder: 894ms.

Что действительно так, как ожидалось, Regex ужасно неэффективно для чего-то такого простого.

42
ответ дан Blindy 26 August 2018 в 21:06
поделиться
string yourWord = "beep boop    baap beep   boop    baap             beep";

yourWord = yourWord .Replace("  ", " |").Replace("| ", "").Replace("|", "");
5
ответ дан Abu Dina 26 August 2018 в 21:06
поделиться

Я знаю, что это действительно старый, но самый простой способ сглаживания пробелов (заменить любой повторяющийся символ пробела одним символом «пробел») следующим образом:

    public static string CompactWhitespace(string astring)
    {
        if (!string.IsNullOrEmpty(astring))
        {
            bool found = false;
            StringBuilder buff = new StringBuilder();

            foreach (char chr in astring.Trim())
            {
                if (char.IsWhiteSpace(chr))
                {
                    if (found)
                    {
                        continue;
                    }

                    found = true;
                    buff.Append(' ');
                }
                else
                {
                    if (found)
                    {
                        found = false;
                    }

                    buff.Append(chr);
                }
            }

            return buff.ToString();
        }

        return string.Empty;
    }
0
ответ дан Brien Halstead 26 August 2018 в 21:06
поделиться
public string GetCorrectString(string IncorrectString)
    {
        string[] strarray = IncorrectString.Split(' ');
        var sb = new StringBuilder();
        foreach (var str in strarray)
        {
            if (str != string.Empty)
            {
                sb.Append(str).Append(' ');
            }
        }
        return sb.ToString().Trim();
    }
0
ответ дан chandudab 26 August 2018 в 21:06
поделиться

Этот фрагмент кода работает хорошо. Я не измеряю производительность.

string text = "   hello    -  world,  here   we go  !!!    a  bc    ";
string.Join(" ", text.Split().Where(x => x != ""));
// Output
// "hello - world, here we go !!! a bc"
1
ответ дан Christian Torrez 26 August 2018 в 21:06
поделиться

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

Результаты:

  1. NormalizeWhiteSpaceForLoop: 156 мс ( by Me - Из моего ответа на удаление всех whispace )
  2. NormalizeWhiteSpace: 267 мс ( от Alex K. )
  3. RegexCompiled: 1950 мс ( от SLaks ])
  4. Regex: 2261 ms ( by SLaks )

Код:

public class RemoveExtraWhitespaces
{
    public static string WithRegex(string text)
    {
        return Regex.Replace(text, @"\s+", " ");
    }

    public static string WithRegexCompiled(Regex compiledRegex, string text)
    {
        return compiledRegex.Replace(text, " ");
    }

    public static string NormalizeWhiteSpace(string input)
    {
        if (string.IsNullOrEmpty(input))
            return string.Empty;

        int current = 0;
        char[] output = new char[input.Length];
        bool skipped = false;

        foreach (char c in input.ToCharArray())
        {
            if (char.IsWhiteSpace(c))
            {
                if (!skipped)
                {
                    if (current > 0)
                        output[current++] = ' ';

                    skipped = true;
                }
            }
            else
            {
                skipped = false;
                output[current++] = c;
            }
        }

        return new string(output, 0, current);
    }

    public static string NormalizeWhiteSpaceForLoop(string input)
    {
        int len = input.Length,
            index = 0,
            i = 0;
        var src = input.ToCharArray();
        bool skip = false;
        char ch;
        for (; i < len; i++)
        {
            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':
                    if (skip) continue;
                    src[index++] = ch;
                    skip = true;
                    continue;
                default:
                    skip = false;
                    src[index++] = ch;
                continue;
            }
        }

        return new string(src, 0, index);
    }
}

Тесты:

[TestFixture]
public class RemoveExtraWhitespacesTest
{
    private const string _text = "foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo foo                  bar                  foobar                     moo ";
    private const string _expected = "foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo foo bar foobar moo ";

    private const int _iterations = 10000;

    [Test]
    public void Regex()
    {
        var result = TimeAction("Regex", () => RemoveExtraWhitespaces.WithRegex(_text));
        Assert.AreEqual(_expected, result);
    }

    [Test]
    public void RegexCompiled()
    {
        var compiledRegex = new Regex(@"\s+", RegexOptions.Compiled);
        var result = TimeAction("RegexCompiled", () => RemoveExtraWhitespaces.WithRegexCompiled(compiledRegex, _text));
        Assert.AreEqual(_expected, result);
    }

    [Test]
    public void NormalizeWhiteSpace()
    {
        var result = TimeAction("NormalizeWhiteSpace", () => RemoveExtraWhitespaces.NormalizeWhiteSpace(_text));
        Assert.AreEqual(_expected, result);
    }

    [Test]
    public void NormalizeWhiteSpaceForLoop()
    {
        var result = TimeAction("NormalizeWhiteSpaceForLoop", () => RemoveExtraWhitespaces.NormalizeWhiteSpaceForLoop(_text));
        Assert.AreEqual(_expected, result);
    }

    public string TimeAction(string name, Func<string> func)
    {
        var timer = Stopwatch.StartNew();
        string result = string.Empty; ;
        for (int i = 0; i < _iterations; i++)
        {
            result = func();
        }

        timer.Stop();
        Console.WriteLine(string.Format("{0}: {1} ms", name, timer.ElapsedMilliseconds));
        return result;
    }
}
15
ответ дан Community 26 August 2018 в 21:06
поделиться
string q = " Hello     how are   you           doing?";
string a = String.Join(" ", q.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries));
6
ответ дан Detlef Kroll 26 August 2018 в 21:06
поделиться

Нет необходимости в сложном коде! Вот простой код, который удалит любые дубликаты:

public static String RemoveCharOccurence(String s, char[] remove)
{
    String s1 = s;
    foreach(char c in remove)
    {
        s1 = RemoveCharOccurence(s1, c);
    }

    return s1;
}

public static String RemoveCharOccurence(String s, char remove)
{
    StringBuilder sb = new StringBuilder(s.Length);

    Boolean removeNextIfMatch = false;
    foreach(char c in s)
    {
        if(c == remove)
        {
            if(removeNextIfMatch)
                continue;
            else
                removeNextIfMatch = true;
        }
        else
            removeNextIfMatch = false;

        sb.Append(c);
    }

    return sb.ToString();
}
-1
ответ дан Dima 26 August 2018 в 21:06
поделиться

В этом вопросе не совсем ясно, какие требования заслуживают.

  1. Вам нужен одиночный символ переднего или заднего пробела?
  2. Когда вы заменяете все пробелы одним символом, вы хотите, чтобы этот символ был последовательным? (т. е. многие из этих решений заменили бы \ t \ t на \ t и '' на '..

Это очень эффективная версия, которая заменяет все пробелы одним пространством и удаляет любое начальное и конечное пробелы перед циклом for.

  public static string WhiteSpaceToSingleSpaces(string input)
  {
    if (input.Length < 2) 
        return input;

    StringBuilder sb = new StringBuilder();

    input = input.Trim();
    char lastChar = input[0];
    bool lastCharWhiteSpace = false;

    for (int i = 1; i < input.Length; i++)
    {
        bool whiteSpace = char.IsWhiteSpace(input[i]);

        //Skip duplicate whitespace characters
        if (whiteSpace && lastCharWhiteSpace)
            continue;

        //Replace all whitespace with a single space.
        if (whiteSpace)
            sb.Append(' ');
        else
            sb.Append(input[i]);

        //Keep track of the last character's whitespace status
        lastCharWhiteSpace = whiteSpace;
    }

    return sb.ToString();
  }
1
ответ дан Jake Drew 26 August 2018 в 21:06
поделиться

попробуйте следующее:

System.Text.RegularExpressions.Regex.Replace(input, @"\s+", " ");
1
ответ дан jaltiere 26 August 2018 в 21:06
поделиться

Я только что взбила это, но еще не проверила. Но я чувствовал, что это изящно и позволяет избежать регулярного выражения:

    /// <summary>
    /// Removes extra white space.
    /// </summary>
    /// <param name="s">
    /// The string
    /// </param>
    /// <returns>
    /// The string, with only single white-space groupings. 
    /// </returns>
    public static string RemoveExtraWhiteSpace(this string s)
    {
        if (s.Length == 0)
        {
            return string.Empty;
        }

        var stringBuilder = new StringBuilder();
        var whiteSpaceCount = 0;
        foreach (var character in s)
        {
            if (char.IsWhiteSpace(character))
            {
                whiteSpaceCount++;
            }
            else
            {
                whiteSpaceCount = 0;
            }

            if (whiteSpaceCount > 1)
            {
                continue;
            }

            stringBuilder.Append(character);
        }

        return stringBuilder.ToString();
    }
0
ответ дан Kris Coleman 26 August 2018 в 21:06
поделиться

Это очень просто, просто используйте метод .Replace():

string words = "Hello     world!";
words = words.Replace("\\s+", " ");

Результат >>> «Привет, мир!»

-1
ответ дан Kurt Van den Branden 26 August 2018 в 21:06
поделиться

Для тех, кто просто хочет скопировать pase и продолжать:

    private string RemoveExcessiveWhitespace(string value)
    {
        if (value == null) { return null; }

        var builder = new StringBuilder();
        var ignoreWhitespace = false;
        foreach (var c in value)
        {
            if (!ignoreWhitespace || c != ' ')
            {
                builder.Append(c);
            }
            ignoreWhitespace = c == ' ';
        }
        return builder.ToString();
    }
0
ответ дан Mert Akcakaya 26 August 2018 в 21:06
поделиться

вы можете использовать indexOf для первого захвата, где начинаются последовательности пробелов, а затем использовать метод replace, чтобы изменить пробел на «». Оттуда вы можете использовать индекс, который вы захватили, и поместить один пробельный символ в это место.

0
ответ дан MGZero 26 August 2018 в 21:06
поделиться

Мне понадобился один из них для больших строк и появился подпрограмма ниже.

Любое последовательное белое пространство (включая вкладки, новые строки) заменяется на все, что находится в normalizeTo. Ведущее / конечное белое пространство удаляется.

Это примерно в 8 раз быстрее, чем RegEx с моими строками char 5k-> 5mil.

internal static string NormalizeWhiteSpace(string input, char normalizeTo = ' ')
{
    if (string.IsNullOrEmpty(input))
        return string.Empty;

    int current = 0;
    char[] output = new char[input.Length];
    bool skipped = false;

    foreach (char c in input.ToCharArray())
    {
        if (char.IsWhiteSpace(c))
        {
            if (!skipped)
            {
                if (current > 0)
                    output[current++] = normalizeTo;

                skipped = true;
            }
        }
        else
        {
            skipped = false;
            output[current++] = c;
        }
    }

    return new string(output, 0, skipped ? current - 1 : current);
}
6
ответ дан Mischa 26 August 2018 в 21:06
поделиться
string text = "foo       bar";
text = Regex.Replace(text, @"\s+", " ");
// text = "foo bar"

Это решение работает с пробелами, вкладками и новой строкой. Если вы хотите просто пробелы, замените '\ s' на '..

6
ответ дан OpticalDelusion 26 August 2018 в 21:06
поделиться
public static string RemoveExtraSpaces(string input)
{
    input = input.Trim();
    string output = "";
    bool WasLastCharSpace = false;
    for (int i = 0; i < input.Length; i++)
    {
        if (input[i] == ' ' && WasLastCharSpace)
            continue;
        WasLastCharSpace = input[i] == ' ';
        output += input[i];
    }
    return output;
}
0
ответ дан Saeed Taran 26 August 2018 в 21:06
поделиться

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

public static String CompactWhitespaces( String s )
{
    StringBuilder sb = new StringBuilder( s );

    CompactWhitespaces( sb );

    return sb.ToString();
}

public static void CompactWhitespaces( StringBuilder sb )
{
    if( sb.Length == 0 )
        return;

    // set [start] to first not-whitespace char or to sb.Length

    int start = 0;

    while( start < sb.Length )
    {
        if( Char.IsWhiteSpace( sb[ start ] ) )
            start++;
        else 
            break;
    }

    // if [sb] has only whitespaces, then return empty string

    if( start == sb.Length )
    {
        sb.Length = 0;
        return;
    }

    // set [end] to last not-whitespace char

    int end = sb.Length - 1;

    while( end >= 0 )
    {
        if( Char.IsWhiteSpace( sb[ end ] ) )
            end--;
        else 
            break;
    }

    // compact string

    int dest = 0;
    bool previousIsWhitespace = false;

    for( int i = start; i <= end; i++ )
    {
        if( Char.IsWhiteSpace( sb[ i ] ) )
        {
            if( !previousIsWhitespace )
            {
                previousIsWhitespace = true;
                sb[ dest ] = ' ';
                dest++;
            }
        }
        else
        {
            previousIsWhitespace = false;
            sb[ dest ] = sb[ i ];
            dest++;
        }
    }

    sb.Length = dest;
}
10
ответ дан Sergey Povalyaev 26 August 2018 в 21:06
поделиться

Вы можете использовать регулярное выражение:

static readonly Regex trimmer = new Regex(@"\s\s+");

s = trimmer.Replace(s, " ");

Для повышения производительности передайте RegexOptions.Compiled.

37
ответ дан SLaks 26 August 2018 в 21:06
поделиться

Это не быстро, но если простота помогает, это работает:

while (text.Contains("  ")) text=text.Replace("  ", " ");
2
ответ дан tinlyx 26 August 2018 в 21:06
поделиться

Я что-то упустил? Я придумал это:

// Input: "HELLO     BEAUTIFUL       WORLD!"
private string NormalizeWhitespace(string inputStr)
{
    // First split the string on the spaces but exclude the spaces themselves
    // Using the input string the length of the array will be 3. If the spaces
    // were not filtered out they would be included in the array
    var splitParts = inputStr.Split(' ').Where(x => x != "").ToArray();

   // Now iterate over the parts in the array and add them to the return
   // string. If the current part is not the last part, add a space after.
   for (int i = 0; i < splitParts.Count(); i++)
   {
        retVal += splitParts[i];
        if (i != splitParts.Count() - 1)
        {
            retVal += " ";
        }
   }
    return retVal;
}
// Would return "HELLO BEAUTIFUL WORLD!"

Я знаю, что создаю вторую строку здесь, чтобы вернуть ее, а также создать массив splitParts. Просто подумал, что это довольно прямолинейно. Возможно, я не учитываю некоторые потенциальные сценарии.

0
ответ дан Tom 26 August 2018 в 21:06
поделиться

Я попытался использовать StringBuilder для:

  1. удалить дополнительные пробельные подстроки
  2. принять символы из цикла по исходной строке, так как Blindy предлагает

Вот лучший баланс производительности & amp; читаемость, которую я нашел (с использованием 100 000 циклов итераций). Иногда это быстрее, чем менее читаемая версия, на 5% медленнее. На моей маленькой тестовой строке регулярное выражение занимает 4,24 раза больше времени.

public static string RemoveExtraWhitespace(string str)
    {
        var sb = new StringBuilder();
        var prevIsWhitespace = false;
        foreach (var ch in str)
        {
            var isWhitespace = char.IsWhiteSpace(ch);
            if (prevIsWhitespace && isWhitespace)
            {
                continue;
            }
            sb.Append(ch);
            prevIsWhitespace = isWhitespace;
        }
        return sb.ToString();
    }
4
ответ дан TTT 26 August 2018 в 21:06
поделиться

Это смешно, но на моем компьютере метод ниже так же быстро, как и подход StringBulder от Сергея Поваляева - (~ 282 мс за 1000 повторений, строки 10k src). Не уверен в использовании памяти.

string RemoveExtraWhiteSpace(string src, char[] wsChars){
   return string.Join(" ",src.Split(wsChars, StringSplitOptions.RemoveEmptyEntries));
}

Очевидно, что все работает хорошо с любыми символами - не просто пробелами.

Хотя это не то, о чем попросил OP, - но если что вы действительно необходимо заменить определенные последовательные символы в строке только одним экземпляром, который вы можете использовать для этого относительно эффективного метода:

    string RemoveDuplicateChars(string src, char[] dupes){  
        var sd = (char[])dupes.Clone();  
        Array.Sort(sd);

        var res = new StringBuilder(src.Length);

        for(int i = 0; i<src.Length; i++){
            if( i==0 || src[i]!=src[i-1] || Array.BinarySearch(sd,src[i])<0){
                res.Append(src[i]); 
            }
        }
        return res.ToString();
    }
0
ответ дан Zar Shardan 26 August 2018 в 21:06
поделиться
Другие вопросы по тегам:

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