501 Stimmen

Effiziente Weise zu entfernen ALLE Leerzeichen aus String?

Ich rufe eine REST-API auf und erhalte eine XML-Antwort zurück. Sie gibt eine Liste von Arbeitsbereichsnamen zurück, und ich schreibe eine schnelle IsExistingWorkspace() Methode. Da alle Arbeitsbereiche aus zusammenhängenden Zeichen ohne Leerzeichen bestehen, nehme ich an, dass der einfachste Weg, um herauszufinden, ob ein bestimmter Arbeitsbereich in der Liste enthalten ist, darin besteht, alle Leerzeichen (einschließlich Zeilenumbrüche) zu entfernen und dies zu tun (XML ist die Zeichenkette, die von der Webanforderung empfangen wird):

XML.Contains("<name>" + workspaceName + "</name>");

Ich weiß, dass zwischen Groß- und Kleinschreibung unterschieden wird, und darauf verlasse ich mich. Ich brauche nur eine Möglichkeit, alle Leerzeichen in einer Zeichenfolge effizient zu entfernen. Ich weiß, RegEx und LINQ kann es tun, aber ich bin offen für andere Ideen. Ich bin vor allem nur über die Geschwindigkeit besorgt.

7 Stimmen

Das Parsen von XML mit Regex ist fast so schlimm wie Parsen von HTML mit Regex .

3 Stimmen

@henk holterman; Siehe meine Antwort unten, regexp scheint nicht in allen Fällen die schnellste zu sein.

0 Stimmen

Regex scheint nicht der schnellste zu sein. Ich habe die Ergebnisse vieler verschiedener Methoden zum Entfernen von Leerzeichen aus einer Zeichenkette zusammengefasst. Die Zusammenfassung ist in einer Antwort unten - stackoverflow.com/a/37347881/582061

31voto

BlueChippy Punkte 5615

Nur eine Alternative, weil es ganz nett aussieht :) - HINWEIS: Henks Antwort ist die schnellste von ihnen.

input.ToCharArray()
 .Where(c => !Char.IsWhiteSpace(c))
 .Select(c => c.ToString())
 .Aggregate((a, b) => a + b);

Testen von 1.000.000 Schleifen auf "This is a simple Test"

Diese Methode = 1,74 Sekunden
Regex = 2,58 Sekunden
new String (Henks) = 0,82 Sekunden

2 Stimmen

Warum wurde dies heruntergestuft? Es ist vollkommen akzeptabel, erfüllt die Anforderungen, funktioniert schneller als die RegEx-Option und ist sehr gut lesbar?

5 Stimmen

Weil es viel kürzer geschrieben werden kann: new string(input.Where(c => !Char.IsWhiteSpace(c)).ToArray());

7 Stimmen

Das mag stimmen - aber die Antwort bleibt bestehen, ist lesbar, schneller als Regex und liefert das gewünschte Ergebnis. Viele der anderen Antworten sind NACH dieser Antwort... daher macht eine Ablehnung keinen Sinn.

26voto

SunsetQuest Punkte 6552

Ich fand ein schöner Bericht über dieses Thema auf CodeProject von Felipe Machado (mit Hilfe von Richard Robertson )

Er testete zehn verschiedene Methoden. Diese ist die schnellste sicher Version...

public static string TrimAllWithInplaceCharArray(string str) {

    var len = str.Length;
    var src = str.ToCharArray();
    int dstIdx = 0;

    for (int i = 0; i < len; i++) {
        var 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':
                continue;

            default:
                src[dstIdx++] = ch;
                break;
        }
    }
    return new string(src, 0, dstIdx);
}

Und die schnellste unsicher Version... (einige Verbesserungen durch Sunsetquest 26.5.2021 )

public static unsafe void RemoveAllWhitespace(ref string str)
{
    fixed (char* pfixed = str)
    {
        char* dst = pfixed;
        for (char* p = pfixed; *p != 0; p++)
        {
            switch (*p)
            {
                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':
                continue;

                default:
                    *dst++ = *p;
                    break;
            }
        }

        uint* pi = (uint*)pfixed;
        ulong len = ((ulong)dst - (ulong)pfixed) >> 1;
        pi[-1] = (uint)len;
        pfixed[len] = '\0';
    }
}

Es gibt auch einige schöne unabhängige Benchmarks auf Stack Overflow von Stian Standahl, die auch zeigen, dass Felipes Funktion etwa 300 % schneller ist als die nächstschnellste Funktion. Für die von mir modifizierte Funktion habe ich außerdem ce Trick.

0 Stimmen

Ich habe versucht, dies in C++ zu übersetzen, aber ich komme nicht weiter. Irgendwelche Ideen, warum meine Portierung scheitern könnte? stackoverflow.com/questions/42135922/

3 Stimmen

Ich kann nicht widerstehen. Schauen Sie in den Kommentarbereich des Artikels, auf den Sie sich beziehen. Sie werden mich als "Basketcase Software" finden. Er und ich haben eine Zeit lang zusammen daran gearbeitet. Ich hatte das völlig vergessen, als dieses Problem wieder auftauchte. Danke für die guten Erinnerungen :)

1 Stimmen

Und was, wenn Sie nur zusätzliche WS entfernen möchten? Wie wäre es mit diesem stackoverflow.com/questions/17770202/ mod ?

15voto

JHM Punkte 371

Wenn Sie eine hervorragende Leistung benötigen, sollten Sie LINQ und reguläre Ausdrücke in diesem Fall vermeiden. Ich habe einige Leistungsvergleiche durchgeführt, und es scheint, dass, wenn Sie Leerzeichen am Anfang und Ende der Zeichenfolge entfernen möchten, string.Trim() die ultimative Funktion ist.

Wenn Sie alle Leerzeichen aus einer Zeichenkette entfernen müssen, funktioniert die folgende Methode am schnellsten von allen, die hier veröffentlicht wurden:

    public static string RemoveWhitespace(this string input)
    {
        int j = 0, inputlen = input.Length;
        char[] newarr = new char[inputlen];

        for (int i = 0; i < inputlen; ++i)
        {
            char tmp = input[i];

            if (!char.IsWhiteSpace(tmp))
            {
                newarr[j] = tmp;
                ++j;
            }
        }
        return new String(newarr, 0, j);
    }

0 Stimmen

Ich wäre neugierig auf die Details Ihrer Benchmarkings - nicht, dass ich skeptisch bin, aber ich bin neugierig auf den Overhead, der mit Linq verbunden ist. Wie schlimm war es?

0 Stimmen

Ich habe nicht alle Tests erneut durchgeführt, aber an so viel kann ich mich erinnern: Alles, was mit Linq zu tun hatte, war viel langsamer als alles ohne Linq. All die clevere Verwendung von String/Char-Funktionen und Konstruktoren machte keinen prozentualen Unterschied, wenn Linq verwendet wurde.

12voto

Maksood Punkte 1110

Regex ist überflüssig; verwenden Sie einfach die Erweiterung auf String (danke Henk). Dies ist trivial und sollte Teil des Frameworks gewesen sein. Wie auch immer, hier ist meine Implementierung:

public static partial class Extension
{
    public static string RemoveWhiteSpace(this string self)
    {
        return new string(self.Where(c => !Char.IsWhiteSpace(c)).ToArray());
    }
}

0 Stimmen

Dies ist im Grunde eine unnötige Antwort (regex ist overkill, aber ist eine schnellere Lösung als die gegebene - und es ist bereits akzeptiert?)

0 Stimmen

Wie kann man Linq-Erweiterungsmethoden auf eine Zeichenkette anwenden? Ich kann nicht herausfinden, welche Verwendung ich vermisse, außer System.Linq

0 Stimmen

Ok sieht aus wie dies nicht in PCL verfügbar ist, IEnumerable<char> ist bedingt in Microsoft String-Implementierung ... Und ich verwende Profil259, das dies nicht unterstützt :)

6voto

larsemil Punkte 812

Ich denke, dass viele Menschen hierher kommen, um Räume zu entfernen:

string s = "my string is nice";
s = s.replace(" ", "");

0 Stimmen

Das Problem dabei ist, dass ein Leerzeichen auf viele verschiedene Arten geschrieben werden kann, wie in anderen Antworten erwähnt. Diese Ersetzung wird in etwa 90%~ der Fälle funktionieren.

2 Stimmen

Seine s.Replace()

0 Stimmen

Ich weiß nicht, woher Sie wissen können, wie die Leute diese Frage finden, aber das ist nicht wichtig, denn es geht nur darum, dass in der Frage ausdrücklich gefragt wird, wie man die alle Leerzeichen was in dieser Antwort nicht der Fall ist.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X