Eine Zustandsmaschine kann es leicht tun, aber es ist wahrscheinlich übertrieben, wenn Sie es nur brauchen, um Leerzeichen zu entfernen
Adrian
Ich habe in einer doppelten Frage einen Benchmark für die verschiedenen Möglichkeiten hinzugefügt . Stackoverflow.com/a/37592018/582061 . Regex war nicht der schnellste Weg, dies zu tun.
Stian Standahl
Antworten:
468
string sentence ="This is a sentence with multiple spaces";RegexOptions options =RegexOptions.None;Regex regex =newRegex("[ ]{2,}", options);
sentence = regex.Replace(sentence," ");
Ich habe das kopiert und eingefügt und es funktioniert. Ich mag REgex wirklich nicht, aber diesmal rettet es mein Leben.
Pokus
9
@Craig ein Kommentar würde ausreichen, IMO. // Dieser Block ersetzt mehrere Leerzeichen durch ein ... :)
Paulwhit
6
Wirklich, RegEx ist dafür übertrieben.
Joel Coehoorn
11
@ Joel: Kann nicht zustimmen. Ich bin mir tatsächlich sicher, dass dieser Weg für ausreichend große Zeichenfolgen effizienter ist als der Ihre und in einer einzigen Zeile ausgeführt werden kann. Wo ist der Overkill?
Konrad Rudolph
24
@ Oscar Joels Code ist keine einfache Schleife durch alle Zeichen! Es ist eine versteckte verschachtelte Schleife mit einem quadratischen Worst-Case. Im Gegensatz dazu ist dieser reguläre Ausdruck linear, baut nur eine einzige Zeichenfolge auf (= drastisch reduzierte Zuordnungskosten im Vergleich zu Joels Code) und außerdem kann die Engine die Hölle daraus optimieren (um ehrlich zu sein, ich bezweifle, dass dies der .NET-Regex ist klug genug dafür, aber theoretisch kann dieser reguläre Ausdruck so billig implementiert werden, dass er nicht einmal mehr lustig ist (er benötigt nur einen DFA mit drei Zuständen, jeweils einem Übergang und keinen zusätzlichen Informationen).
Konrad Rudolph
623
Ich benutze gerne:
myString =Regex.Replace(myString,@"\s+"," ");
Da es Läufe von Leerzeichen aller Art (z. B. Tabulatoren, Zeilenumbrüche usw.) abfängt und durch ein einzelnes Leerzeichen ersetzt.
Leichte Änderung: Regex.Replace (Quelle, @ "(\ s) \ s +", "$ 1"); Dies gibt den ersten gefundenen Leerzeichen-Typ zurück. Wenn Sie also 5 Registerkarten haben, wird eine Registerkarte zurückgegeben. Falls jemand dies bevorzugt.
FB zehn Kate
@radistao Ihr Link ist für das Ersetzen von Javascript-Zeichenfolgen, nicht für C #.
Shiva
1
@Shiva, / \ s \ s + / ist eine Standard-POSIX-Regex-Anweisung und kann in jeder Sprache mit eigener Syntax konvertiert / verwendet werden
radistao
4
Im Sinne der Lösung von @ FBtenKate: Regex.Replace (Quelle, @ "(\ s) \ 1+", "$ 1"); ersetzt mehrere identische aufeinanderfolgende Zeichen durch ein einzelnes.
François Beaune
1
Um führende und nachfolgende Leerzeichen zu entfernen, sollten Sie die Funktion Trim () mit dieser Funktion verwenden, z. B. var myString = Regex.Replace (myString, @ "\ s +", "") .Trim ();
Dies ist besser lesbar als Regex, ich bevorzuge es mehr, weil ich keine andere Syntax lernen muss
Michael Bahig
9
Ich mag es, weil es Regex nicht braucht
AleX_
3
Dies wäre für große Saiten ineffizient.
DarcyThomas
3
Dadurch werden auch führende und nachfolgende Leerzeichen entfernt.
Matzi
1
Ich bevorzuge auch diese Antwort. Mein alter Mentor pflegte zu sagen: "Immer wenn Sie ein Problem haben, von dem Sie glauben, dass Sie Regex brauchen, um es zu lösen, nun ... jetzt haben Sie ZWEI Probleme" <wink>
William Madonna Jr.
38
Ich denke, Matts Antwort ist die beste, aber ich glaube nicht, dass es ganz richtig ist. Wenn Sie Zeilenumbrüche ersetzen möchten, müssen Sie Folgendes verwenden:
RegexOptions.Multiline ändert die Bedeutung von ^ und $ so, dass sie mit dem Anfang und Ende jeder Zeile ($ = \ n) anstelle der gesamten mehrzeiligen Zeichenfolge übereinstimmen. Da \ s [\ f \ n \ r \ t \ v] entspricht, sollten die Zeilenumbrüche ersetzt werden, auch wenn die Option Mehrzeilig deaktiviert ist.
SushiGuy
1
Matts Antwort hat dies bereits behandelt. Ich 'glaube', dass 30 Personen diese Antwort nur mit verbundenen Augen
Dies ist weitaus weniger effizient als der reguläre Ausdruck "{2,}", wenn die Zeichenfolge Sequenzen mit 3 oder mehr Leerzeichen enthält.
Jan Goyvaerts
2
@ JanGoyvaerts: Selbst mit 10 Leerzeichen war die Regex langsamer, als ich einen schnellen und schmutzigen Test machte. Davon abgesehen ist nur ein riesiger Teilstring voller Leerzeichen erforderlich, um die Leistung der while-Schleife vollständig zu beenden. Aus Fairnessgründen habe ich RegexOptions.Compiled anstelle des langsameren Regex.Replace verwendet.
Brian
5
RegexOptions.Compiled fügt viel Aufwand hinzu, um den Regex in IL zu kompilieren. Verwenden Sie es nur, wenn Ihre Anwendung den regulären Ausdruck häufig genug oder auf ausreichend großen Zeichenfolgen verwendet, damit die erhöhte Übereinstimmungsgeschwindigkeit die verringerte Kompilierungsgeschwindigkeit ausgleicht.
Jan Goyvaerts
Dies ist ein Beispiel für extrem ineffizienten Code. LOL.
pcbabu
1
@pcbabu Es ist nicht so schlimm, wie es in vielen Fällen scheint. Die Replace()Methode behandelt alle Vorkommen von zwei Leerzeichen in einer bestimmten Zeichenfolge, sodass wir nicht für jede Instanz gepaarter Leerzeichen in der Zeichenfolge eine Schleife erstellen (und eine ganze Zeichenfolge neu zuweisen). Eine neue Zuordnung behandelt alle. Wir führen die Schleife nur dann erneut aus, wenn 3 oder mehr Leerzeichen zusammen vorhanden sind, was bei vielen Eingabequellen wahrscheinlich seltener vorkommt. Wenn Sie zeigen können, dass es ein Problem für Ihre Daten wird, schreiben Sie die Zustandsmaschine, um Zeichen für Zeichen in einen neuen Stringbuilder zu verschieben.
Joel Coehoorn
21
Regex kann selbst bei einfachen Aufgaben ziemlich langsam sein. Dadurch wird eine Erweiterungsmethode erstellt, die von jedem verwendet werden kann string.
publicstaticclassStringExtension{publicstaticStringReduceWhitespace(thisStringvalue){var newString =newStringBuilder();bool previousIsWhitespace =false;for(int i =0; i <value.Length; i++){if(Char.IsWhiteSpace(value[i])){if(previousIsWhitespace){continue;}
previousIsWhitespace =true;}else{
previousIsWhitespace =false;}
newString.Append(value[i]);}return newString.ToString();}}
Es würde als solches verwendet werden:
string testValue ="This contains too much whitespace."
testValue = testValue.ReduceWhitespace();// testValue = "This contains too much whitespace."
Für diejenigen, die nicht mögen Regex, ist hier eine Methode, die verwendet StringBuilder:
publicstaticstringFilterWhiteSpaces(string input){if(input ==null)returnstring.Empty;StringBuilder stringBuilder =newStringBuilder(input.Length);for(int i =0; i < input.Length; i++){char c = input[i];if(i ==0|| c !=' '||(c ==' '&& input[i -1]!=' '))
stringBuilder.Append(c);}return stringBuilder.ToString();}
In meinen Tests war diese Methode mit einem sehr großen Satz kleiner bis mittlerer Zeichenfolgen im Durchschnitt 16-mal schneller als mit einem statisch kompilierten Regex. Im Vergleich zu einem nicht kompilierten oder nicht statischen Regex sollte dies noch schneller sein.
Beachten Sie, dass führende oder nachfolgende Leerzeichen nicht entfernt werden , sondern nur das mehrfache Auftreten solcher Leerzeichen.
Sie müssen sicherstellen, dass Ihre Zeichenfolge nicht "()" oder ") (" enthält. Oder "wel()come to london)("wird "wel come to london". Sie könnten versuchen, viele Klammern zu verwenden. Verwenden Sie also ((((()))))anstelle von ()und )))))(((((anstelle von )(. Es wird immer noch funktionieren. Trotzdem, wenn Die Zeichenfolge enthält ((((()))))oder )))))(((((, dies wird fehlschlagen.
nmit026
7
Dies ist eine kürzere Version, die nur verwendet werden sollte, wenn Sie dies nur einmal tun, da bei Regexjedem Aufruf eine neue Instanz der Klasse erstellt wird.
temp =newRegex(" {2,}").Replace(temp," ");
Wenn Sie mit regulären Ausdrücken nicht allzu vertraut sind, finden Sie hier eine kurze Erklärung:
Der {2,}Regex sucht nach dem Zeichen davor und findet Teilzeichenfolgen zwischen 2 und unbegrenzt oft.
Das .Replace(temp, " ")ersetzt alle Übereinstimmungen in der Zeichenfolgentemp durch ein Leerzeichen.
Wenn Sie dies mehrmals verwenden möchten, ist hier eine bessere Option, da die Regex-IL zur Kompilierungszeit erstellt wird:
Ein Wort der Vorsicht: Die Verwendung von Split ist zwar sehr einfach zu verstehen, kann jedoch überraschend negative Auswirkungen auf die Leistung haben. Da viele Zeichenfolgen erstellt werden können, müssen Sie Ihre Speichernutzung überwachen, wenn Sie mit dieser Methode große Zeichenfolgen verarbeiten.
Pac0
5
Andere Antworten trösten, per Joel, und hoffentlich leicht verbessern, wenn ich gehe:
Eines der coolen Dinge dabei ist, dass es mit Sammlungen funktioniert, die keine Zeichenfolgen sind, indem ToString () für die Elemente aufgerufen wird. Die Verwendung ist immer noch die gleiche:
//...string s =" 1 2 4 5".Split(" ".ToCharArray(),StringSplitOptions.RemoveEmptyEntries).Join(" ");
Warum eine Erweiterungsmethode erstellen? Warum nicht einfach string.Join () verwenden?
Eric Schoonover
3
// Mysample stringstring str ="hi you are a demo";//Split the words based on white sapcevar demo= str .Split(' ').Where(s =>!string.IsNullOrWhiteSpace(s));//Join the values back and add a single space in between
str =string.Join(" ", demo);//output: string str ="hi you are a demo";
Ich weiß, dass dies ziemlich alt ist, bin aber darauf gestoßen, als ich versucht habe, fast das Gleiche zu erreichen. Diese Lösung wurde in RegEx Buddy gefunden. Dieses Muster ersetzt alle doppelten Leerzeichen durch einzelne Leerzeichen und schneidet auch führende und nachfolgende Leerzeichen.
pattern:(?m:^+|+$|(){2,})
replacement: $1
Es ist ein wenig schwer zu lesen, da es sich um einen leeren Raum handelt. Hier werden also wieder die "Räume" durch ein "_" ersetzt.
pattern:(?m:^_+|_+$|(_){2,})<-- don't use this, just for illustration.
Das Konstrukt "(? M:" aktiviert die Option "mehrzeilig". Im Allgemeinen möchte ich alle möglichen Optionen in das Muster selbst aufnehmen, damit es eigenständiger ist.
Viele Antworten liefern die richtige Ausgabe, aber für diejenigen, die nach den besten Leistungen suchen, habe ich Nolanars Antwort (die die beste Antwort für die Leistung war) um etwa 10% verbessert .
publicstaticstringMergeSpaces(thisstring str){if(str ==null){returnnull;}else{StringBuilder stringBuilder =newStringBuilder(str.Length);int i =0;foreach(char c in str){if(c !=' '|| i ==0|| str[i -1]!=' ')
stringBuilder.Append(c);
i++;}return stringBuilder.ToString();}}
while word.contains(" ")//double space
word = word.Replace(" "," ");//replace double space by single space.
word = word.trim();//to remove single whitespces from start & end.
Dies wird die nachgestellten Leerzeichen entfernen
The_Black_Smurf
Entschuldigung für den Fehler, ich habe den Code behoben, jetzt funktioniert es wie erwartet getestet Zeichenfolge: "1 2 3 4 9" Ergebniszeichenfolge: "1 2 3 4 9"
using System;
using System.Linq;
using System.Text;publicstaticclassStringExtension{publicstaticstringStripSpaces(thisstring s){return s.Aggregate(newStringBuilder(),(acc, c)=>{if(c !=' '|| acc.Length>0&& acc[acc.Length-1]!=' ')
acc.Append(c);return acc;}).ToString();}publicstaticvoidMain(){Console.WriteLine("\""+StringExtension.StripSpaces("1 Hello World 2 ")+"\"");}}
Antworten:
quelle
Ich benutze gerne:
Da es Läufe von Leerzeichen aller Art (z. B. Tabulatoren, Zeilenumbrüche usw.) abfängt und durch ein einzelnes Leerzeichen ersetzt.
quelle
quelle
Ich denke, Matts Antwort ist die beste, aber ich glaube nicht, dass es ganz richtig ist. Wenn Sie Zeilenumbrüche ersetzen möchten, müssen Sie Folgendes verwenden:
quelle
Ein weiterer Ansatz, der LINQ verwendet:
quelle
Es ist viel einfacher als das alles:
quelle
Replace()
Methode behandelt alle Vorkommen von zwei Leerzeichen in einer bestimmten Zeichenfolge, sodass wir nicht für jede Instanz gepaarter Leerzeichen in der Zeichenfolge eine Schleife erstellen (und eine ganze Zeichenfolge neu zuweisen). Eine neue Zuordnung behandelt alle. Wir führen die Schleife nur dann erneut aus, wenn 3 oder mehr Leerzeichen zusammen vorhanden sind, was bei vielen Eingabequellen wahrscheinlich seltener vorkommt. Wenn Sie zeigen können, dass es ein Problem für Ihre Daten wird, schreiben Sie die Zustandsmaschine, um Zeichen für Zeichen in einen neuen Stringbuilder zu verschieben.Regex kann selbst bei einfachen Aufgaben ziemlich langsam sein. Dadurch wird eine Erweiterungsmethode erstellt, die von jedem verwendet werden kann
string
.Es würde als solches verwendet werden:
quelle
quelle
Für diejenigen, die nicht mögen
Regex
, ist hier eine Methode, die verwendetStringBuilder
:In meinen Tests war diese Methode mit einem sehr großen Satz kleiner bis mittlerer Zeichenfolgen im Durchschnitt 16-mal schneller als mit einem statisch kompilierten Regex. Im Vergleich zu einem nicht kompilierten oder nicht statischen Regex sollte dies noch schneller sein.
Beachten Sie, dass führende oder nachfolgende Leerzeichen nicht entfernt werden , sondern nur das mehrfache Auftreten solcher Leerzeichen.
quelle
Sie können dies einfach in einer einzeiligen Lösung tun!
Sie können andere Klammern (oder sogar andere Zeichen) auswählen, wenn Sie möchten.
quelle
"wel()come to london)("
wird"wel come to london"
. Sie könnten versuchen, viele Klammern zu verwenden. Verwenden Sie also((((()))))
anstelle von()
und)))))(((((
anstelle von)(
. Es wird immer noch funktionieren. Trotzdem, wenn Die Zeichenfolge enthält((((()))))
oder)))))(((((
, dies wird fehlschlagen.Dies ist eine kürzere Version, die nur verwendet werden sollte, wenn Sie dies nur einmal tun, da bei
Regex
jedem Aufruf eine neue Instanz der Klasse erstellt wird.Wenn Sie mit regulären Ausdrücken nicht allzu vertraut sind, finden Sie hier eine kurze Erklärung:
Der
{2,}
Regex sucht nach dem Zeichen davor und findet Teilzeichenfolgen zwischen 2 und unbegrenzt oft.Das
.Replace(temp, " ")
ersetzt alle Übereinstimmungen in der Zeichenfolgentemp durch ein Leerzeichen.Wenn Sie dies mehrmals verwenden möchten, ist hier eine bessere Option, da die Regex-IL zur Kompilierungszeit erstellt wird:
quelle
no Regex, no Linq ... entfernt führende und nachfolgende Leerzeichen und reduziert alle eingebetteten Mehrfachraumsegmente auf ein Leerzeichen
Ergebnis: "0 1 2 3 4 5"
quelle
Andere Antworten trösten, per Joel, und hoffentlich leicht verbessern, wenn ich gehe:
Sie können dies tun mit
Regex.Replace()
:Oder mit
String.Split()
:quelle
Ich habe gerade eine neue geschrieben
Join
, die mir gefällt, also dachte ich, ich würde damit antworten:Eines der coolen Dinge dabei ist, dass es mit Sammlungen funktioniert, die keine Zeichenfolgen sind, indem ToString () für die Elemente aufgerufen wird. Die Verwendung ist immer noch die gleiche:
quelle
quelle
Ich weiß, dass dies ziemlich alt ist, bin aber darauf gestoßen, als ich versucht habe, fast das Gleiche zu erreichen. Diese Lösung wurde in RegEx Buddy gefunden. Dieses Muster ersetzt alle doppelten Leerzeichen durch einzelne Leerzeichen und schneidet auch führende und nachfolgende Leerzeichen.
Es ist ein wenig schwer zu lesen, da es sich um einen leeren Raum handelt. Hier werden also wieder die "Räume" durch ein "_" ersetzt.
Das Konstrukt "(? M:" aktiviert die Option "mehrzeilig". Im Allgemeinen möchte ich alle möglichen Optionen in das Muster selbst aufnehmen, damit es eigenständiger ist.
quelle
Viele Antworten liefern die richtige Ausgabe, aber für diejenigen, die nach den besten Leistungen suchen, habe ich Nolanars Antwort (die die beste Antwort für die Leistung war) um etwa 10% verbessert .
quelle
Ich kann damit Leerzeichen entfernen
quelle
Verwenden Sie das Regex-Muster
quelle
Versuchen Sie diese Methode
benutze es so:
quelle
Hier ist eine geringfügige Änderung der ursprünglichen Antwort von Nolonar .
Überprüfen Sie Folgendes, um zu überprüfen, ob das Zeichen nicht nur ein Leerzeichen, sondern ein Leerzeichen ist:
Es werden mehrere Leerzeichen durch ein einzelnes Leerzeichen ersetzt.
quelle
Alte Schule:
quelle
Ohne reguläre Ausdrücke zu verwenden:
OK für kurze Saiten, aber für lange Saiten mit viel Leerzeichen schlecht.
quelle
Mix aus StringBuilder und Enumerable.Aggregate () als Erweiterungsmethode für Strings:
Eingang:
Ausgabe:
quelle