automat państwowy może to łatwo zrobić, ale prawdopodobnie jest to przesada, jeśli potrzebujesz go tylko do usuwania spacji
Adrian
Dodałem test porównawczy na różne sposoby, aby to zrobić w duplikacie pytania stackoverflow.com/a/37592018/582061 . Regex nie był najszybszym sposobem na to.
Stian Standahl
Odpowiedzi:
468
string sentence ="This is a sentence with multiple spaces";RegexOptions options =RegexOptions.None;Regex regex =newRegex("[ ]{2,}", options);
sentence = regex.Replace(sentence," ");
Mam to skopiować i wkleić i to działa. Naprawdę nie lubię REgex, ale tym razem ratuje mi życie.
Pokus
9
@Craig wystarczy komentarz, IMO. // Ten blok zastępuje wiele spacji jednym ... :)
paulwhit
6
Naprawdę, RegEx jest do tego przesadny.
Joel Coehoorn
11
@Joel: Nie mogę się zgodzić. Jestem pewien, że ten sposób jest bardziej wydajny niż twój dla wystarczająco dużych ciągów i można to zrobić w jednym wierszu. Gdzie jest przesada?
Konrad Rudolph,
24
@Oscar Kod Joela nie jest prostą pętlą wszystkich znaków! Jest to ukryta zagnieżdżona pętla, która ma kwadratowy najgorszy przypadek. Z kolei to wyrażenie regularne jest liniowe, tworzy tylko jeden ciąg (= drastycznie zmniejszone koszty alokacji w porównaniu z kodem Joela), a ponadto silnik może go zoptymalizować (szczerze mówiąc, wątpię, czy wyrażenie regularne .NET to wystarczająco inteligentne, ale teoretycznie to wyrażenie regularne można wdrożyć tak tanio, że nie jest już nawet śmieszne; potrzebuje tylko DFA z trzema stanami, jednym przejściem i bez dodatkowych informacji).
Konrad Rudolph
624
Lubię używać:
myString =Regex.Replace(myString,@"\s+"," ");
Ponieważ wyłapuje biegi dowolnego rodzaju białych znaków (np. Tabulatory, znaki nowej linii itp.) I zastępuje je pojedynczą spacją.
Nieznaczna modyfikacja: Regex.Replace (source, @ "(\ s) \ s +", "$ 1"); Zwróci pierwszy znaleziony typ białych znaków. Więc jeśli masz 5 kart, zwróci kartę. Jeśli ktoś woli to.
FB ten Kate
@radistao Twój link zastępuje ciąg JavaScript, a nie C #.
Shiva
1
@Shiva, / \ s \ s + / to standardowa instrukcja wyrażenia regularnego POSIX i może być konwertowana / używana w dowolnym języku przy użyciu własnej składni
radistao
4
W duchu rozwiązania @ FBtenKate: Regex.Replace (source, @ "(\ s) \ 1+", "$ 1"); zastąpi wiele identycznych kolejnych znaków jednym.
François Beaune,
1
w celu usunięcia początkowych i końcowych białych znaków należy użyć funkcji Trim () z tym ,, jak var myString = Regex.Replace (myString, @ "\ s +", "") .Trim ();
Jest to bardziej czytelne niż regex, wolę to bardziej, ponieważ nie muszę się uczyć innej składni
Michael Bahig
9
Podoba mi się, ponieważ nie potrzebuje Regex
AleX_
3
Byłoby to nieefektywne w przypadku dużych ciągów.
DarcyThomas,
3
Usuwa to również spacje wiodące i końcowe.
Matzi
1
Ja też wolę tę odpowiedź. Mój stary mentor mawiał: „za każdym razem, gdy masz problem, który Twoim zdaniem potrzebujesz Regex do rozwiązania, cóż ... teraz masz DWIE problemy” <wink>
William Madonna Jr.
38
Myślę, że odpowiedź Matta jest najlepsza, ale nie sądzę, żeby była słuszna. Jeśli chcesz zastąpić znaki nowej linii, musisz użyć:
RegexOptions.Multiline zmienia znaczenie ^ i $, tak aby pasowały do początku i końca każdej linii ($ = \ n), zamiast całego ciągu wielowierszowego. Ponieważ \ s jest równoważne z [\ f \ n \ r \ t \ v], nowe linie powinny zostać zastąpione, nawet jeśli opcja Multiline jest wyłączona.
SushiGuy
1
Odpowiedź Matta już to omówiła. „Wierzę”, że 30 osób właśnie z zawiązanymi oczami podniosło głos na tę odpowiedź :)
Będzie to znacznie mniej wydajne niż wyrażenie regularne {2,}, jeśli ciąg zawiera sekwencje 3 lub więcej spacji.
Jan Goyvaerts,
2
@JGGoyvaerts: Nawet z 10 spacjami regex był wolniejszy, kiedy wykonałem szybki i brudny test. To powiedziawszy, wystarczy jeden gigantyczny substrat pełen przestrzeni, aby całkowicie zabić działanie pętli while. Dla uczciwości użyłem RegexOptions.Compiled zamiast wolniejszego Regex.Replace.
Brian
5
RegexOptions.Compiled dodaje wiele narzutów związanych z kompilacją wyrażenia regularnego w IL. Nie używaj go, chyba że twoja aplikacja będzie używała wyrażenia regularnego wystarczająco często lub na wystarczająco dużych ciągach, aby zwiększona dopasowana prędkość kompensowała zmniejszoną prędkość kompilacji.
Jan Goyvaerts
To jest przykład skrajnie nieefektywnego kodu. LOL.
pcbabu
1
@pcbabu Nie jest tak źle, jak się wydaje w wielu przypadkach. Replace()Metoda będzie obsługiwać wszystkie wystąpienia dwóch miejsc w danym ciągu znaków, więc nie jesteśmy w pętli (i realokacji cały łańcuch) dla każdej instancji sparowanych przestrzeni w ciąg. Jeden nowy przydział obsłuży je wszystkie. Ponownie uruchamiamy pętlę tylko wtedy, gdy są razem 3 lub więcej spacji, co może być rzadsze w przypadku wielu źródeł wejściowych. Jeśli możesz pokazać, że staje się to problemem dla twoich danych, to idź napisz maszynę stanu, aby wypychać znak po znaku do nowego programu budującego łańcuchy.
Joel Coehoorn
21
Regex może być powolny nawet przy prostych zadaniach. Tworzy to metodę rozszerzenia, której można użyć z dowolnej 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();}}
Byłby używany jako taki:
string testValue ="This contains too much whitespace."
testValue = testValue.ReduceWhitespace();// testValue = "This contains too much whitespace."
Dla tych, którzy nie lubią Regex, oto metoda, która wykorzystuje 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();}
W moich testach ta metoda była średnio 16 razy szybsza przy bardzo dużym zestawie łańcuchów od małych do średnich, w porównaniu do regexu skompilowanego statycznie. W porównaniu z nieskompilowanym lub niestatycznym regeksem powinno to być jeszcze szybsze.
Pamiętaj, że nie usuwa początkowych ani końcowych spacji, a tylko ich wielokrotne wystąpienie.
Musisz upewnić się, że Twój ciąg nie zawiera „()” lub „) (”. Lub stanie "wel()come to london)("się "wel come to london". Możesz spróbować użyć wielu nawiasów. Więc użyj ((((()))))zamiast ()i )))))(((((zamiast )(. Będzie nadal działać. Wciąż, jeśli ciąg zawiera ((((()))))lub )))))(((((, to się nie powiedzie
nmit026
7
Jest to krótsza wersja, z której należy korzystać tylko wtedy, gdy robisz to tylko raz, ponieważ tworzy ona nową instancję Regexklasy za każdym razem, gdy jest wywoływana.
temp =newRegex(" {2,}").Replace(temp," ");
Jeśli nie znasz zbyt dobrze wyrażeń regularnych, oto krótkie wyjaśnienie:
{2,}Sprawia, że przeszukiwanie regex dla znaku poprzedzającego go i wyszukuje podciągi między 2 i nieograniczony czas. Zastępuje wszystkie mecze w temp ciąg z kosmosu. .Replace(temp, " ")
Jeśli chcesz użyć tego wielokrotnie, oto lepsza opcja, ponieważ tworzy ona wyrażenie regularne w czasie kompilacji:
Słowo ostrzeżenia: użycie podziału, choć bardzo proste do zrozumienia, może mieć zaskakująco negatywny wpływ na wydajność. Ponieważ można utworzyć wiele ciągów, będziesz musiał obserwować zużycie pamięci w przypadku obsługi dużych ciągów za pomocą tej metody.
Pac0,
5
Pocieszając inne odpowiedzi, według Joela, i mam nadzieję, że nieco się poprawię:
po co tworzyć metodę rozszerzenia? dlaczego nie użyć po prostu string.Join ()?
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";
Wiem, że to dość stare, ale natknąłem się na to, próbując osiągnąć prawie to samo. Znaleziono to rozwiązanie w RegEx Buddy. Ten wzór zastąpi wszystkie podwójne spacje pojedynczymi spacjami, a także przycina początkowe i końcowe spacje.
pattern:(?m:^+|+$|(){2,})
replacement: $1
Jest trochę trudny do odczytania, ponieważ mamy do czynienia z pustą przestrzenią, więc tutaj znowu jest to z „spacjami” zastąpionymi przez „_”.
pattern:(?m:^_+|_+$|(_){2,})<-- don't use this, just for illustration.
Konstrukcja „(? M:” włącza opcję „wielu linii”. Zazwyczaj lubię zawrzeć dowolne opcje w obrębie samego wzorca, aby był bardziej samodzielny.
Wiele odpowiedzi zapewnia właściwą wydajność, ale dla tych, którzy szukają najlepszych wyników, poprawiłem odpowiedź Nolanara (która była najlepszą odpowiedzią na wydajność) o około 10%.
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.
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 ")+"\"");}}
Odpowiedzi:
źródło
Lubię używać:
Ponieważ wyłapuje biegi dowolnego rodzaju białych znaków (np. Tabulatory, znaki nowej linii itp.) I zastępuje je pojedynczą spacją.
źródło
źródło
Myślę, że odpowiedź Matta jest najlepsza, ale nie sądzę, żeby była słuszna. Jeśli chcesz zastąpić znaki nowej linii, musisz użyć:
źródło
Inne podejście wykorzystujące LINQ:
źródło
To o wiele prostsze niż wszystko:
źródło
Replace()
Metoda będzie obsługiwać wszystkie wystąpienia dwóch miejsc w danym ciągu znaków, więc nie jesteśmy w pętli (i realokacji cały łańcuch) dla każdej instancji sparowanych przestrzeni w ciąg. Jeden nowy przydział obsłuży je wszystkie. Ponownie uruchamiamy pętlę tylko wtedy, gdy są razem 3 lub więcej spacji, co może być rzadsze w przypadku wielu źródeł wejściowych. Jeśli możesz pokazać, że staje się to problemem dla twoich danych, to idź napisz maszynę stanu, aby wypychać znak po znaku do nowego programu budującego łańcuchy.Regex może być powolny nawet przy prostych zadaniach. Tworzy to metodę rozszerzenia, której można użyć z dowolnej
string
.Byłby używany jako taki:
źródło
źródło
Dla tych, którzy nie lubią
Regex
, oto metoda, która wykorzystujeStringBuilder
:W moich testach ta metoda była średnio 16 razy szybsza przy bardzo dużym zestawie łańcuchów od małych do średnich, w porównaniu do regexu skompilowanego statycznie. W porównaniu z nieskompilowanym lub niestatycznym regeksem powinno to być jeszcze szybsze.
Pamiętaj, że nie usuwa początkowych ani końcowych spacji, a tylko ich wielokrotne wystąpienie.
źródło
Możesz to zrobić w jednym rozwiązaniu!
Możesz wybrać inne nawiasy (lub nawet inne znaki), jeśli chcesz.
źródło
"wel()come to london)("
się"wel come to london"
. Możesz spróbować użyć wielu nawiasów. Więc użyj((((()))))
zamiast()
i)))))(((((
zamiast)(
. Będzie nadal działać. Wciąż, jeśli ciąg zawiera((((()))))
lub)))))(((((
, to się nie powiedzieJest to krótsza wersja, z której należy korzystać tylko wtedy, gdy robisz to tylko raz, ponieważ tworzy ona nową instancję
Regex
klasy za każdym razem, gdy jest wywoływana.Jeśli nie znasz zbyt dobrze wyrażeń regularnych, oto krótkie wyjaśnienie:
{2,}
Sprawia, że przeszukiwanie regex dla znaku poprzedzającego go i wyszukuje podciągi między 2 i nieograniczony czas. Zastępuje wszystkie mecze w temp ciąg z kosmosu..Replace(temp, " ")
Jeśli chcesz użyć tego wielokrotnie, oto lepsza opcja, ponieważ tworzy ona wyrażenie regularne w czasie kompilacji:
źródło
bez Regex, bez Linq ... usuwa początkowe i końcowe spacje, a także redukuje osadzone segmenty wielu spacji do jednego spacji
wynik: „0 1 2 3 4 5”
źródło
Pocieszając inne odpowiedzi, według Joela, i mam nadzieję, że nieco się poprawię:
Możesz to zrobić za pomocą
Regex.Replace()
:Lub z
String.Split()
:źródło
Właśnie napisałem nowy,
Join
który mi się podoba, więc pomyślałem, że odpowiem ponownie:Jedną z fajnych rzeczy jest to, że działa z kolekcjami, które nie są łańcuchami, wywołując ToString () na elementach. Użycie jest nadal takie samo:
źródło
źródło
Wiem, że to dość stare, ale natknąłem się na to, próbując osiągnąć prawie to samo. Znaleziono to rozwiązanie w RegEx Buddy. Ten wzór zastąpi wszystkie podwójne spacje pojedynczymi spacjami, a także przycina początkowe i końcowe spacje.
Jest trochę trudny do odczytania, ponieważ mamy do czynienia z pustą przestrzenią, więc tutaj znowu jest to z „spacjami” zastąpionymi przez „_”.
Konstrukcja „(? M:” włącza opcję „wielu linii”. Zazwyczaj lubię zawrzeć dowolne opcje w obrębie samego wzorca, aby był bardziej samodzielny.
źródło
Wiele odpowiedzi zapewnia właściwą wydajność, ale dla tych, którzy szukają najlepszych wyników, poprawiłem odpowiedź Nolanara (która była najlepszą odpowiedzią na wydajność) o około 10%.
źródło
Dzięki temu mogę usunąć białe spacje
źródło
Użyj wzorca wyrażenia regularnego
źródło
wypróbuj tę metodę
użyj tego w ten sposób:
źródło
Oto niewielkie modyfikacje na Nolonar oryginalnej odpowiedzi .
Aby sprawdzić, czy znak nie jest tylko spacją, ale dowolną spacją, użyj tego:
Zastąpi wiele znaków białych znaków pojedynczą spacją.
źródło
Stary skool:
źródło
Bez użycia wyrażeń regularnych:
OK, aby używać na krótkich ciągach, ale będzie źle działać na długich ciągach z dużą ilością spacji.
źródło
Mieszanka StringBuilder i Enumerable.Aggregate () jako metody rozszerzenia ciągów:
Wejście:
Wynik:
źródło