Podziel ciąg przez inny ciąg w C #

682

Używam tej Split()metody do dzielenia ciągów, ale wydaje się, że działa to tylko wtedy, gdy dzielisz ciąg znaków na znak. Czy istnieje sposób na podzielenie a string, przy czym innym ciągiem jest podział według parametru?

Próbowałem przekształcić rozdzielacz w tablicę znaków, ale bez powodzenia.

Innymi słowy, chciałbym podzielić string:

THExxQUICKxxBROWNxxFOX

przez xxi zwraca tablicę z wartościami:

SZYBKI BRĄZOWY LIS

Brandon
źródło
2
Jeśli chodzi o przyszłe obawy: zainteresował mnie jeden z poniższych komentarzy, dlatego postanowiłem rozpocząć dyskusję na temat inżynierii oprogramowania dotyczącą nieintuicyjnego (ale właściwego) sposobu na zrobienie tego w przyjętej odpowiedzi.
scharette

Odpowiedzi:

1239

Aby podzielić przez ciąg, musisz użyć przeciążenia tablicy ciągów .

string data = "THExxQUICKxxBROWNxxFOX";

return data.Split(new string[] { "xx" }, StringSplitOptions.None);
Adam Robinson
źródło
4
W rzeczywistości zmieniłem odpowiedź na to z dwóch powodów: # 1: Aby obsłużyć podziały, które chcę zrobić, musiałbym użyć Regex.Escape, ponieważ mój podzielony ciąg często zawiera gwiazdki, itp. # 2: Podczas tego programu Piszę nie wymaga prawdziwej optymalizacji, wydaje się, że korzystanie z metody Regex Split wiąże się z dodatkowymi kosztami.
Brandon
7
@Peter: W tym poście Jon sugeruje to, ponieważ plakat nie ma ustalonego ogranicznika; chce podzielić ciągi znaków oddzielone „więcej niż jedną spacją” (co oznacza 2+). W przypadku ciągów ograniczonych wzorem, a nie wartością , RegEx jest świetną (no, jedyną ) opcją. W przypadku ograniczników o stałej wartości wprowadza niepotrzebne koszty ogólne. Spróbuj uruchomić test; wraz ze wzrostem liczby operacji RegEx kończy się około 10 razy tak długo, jak odpowiada string.Split.
Adam Robinson
9
Pochodzę z Python do C #. Python obsługuje ciąg podzielony przez inny ciąg. I często muszę wracać do tego pytania, aby uzyskać prostą odpowiedź string[] Split(string pattern), co jest najbardziej naturalnym sposobem, jaki mogłem wymyślić, ale jeszcze go nie ma. Napisałem C wcześniej, więc jestem przyzwyczajony do znakowania tablic, ale nadal nie lubię patrzeć na char[]wyskakujące kody C #, ponieważ nagle przyciąga moją uwagę z poziomu strumienia na poziom bajtów. Czy ktoś wie, dlaczego faceci z biblioteki C # zaprojektowali taką metodę podziału? Jeśli istnieje dobry powód, prawdopodobnie będę mógł docenić to pomimo niedogodności.
foresightyj
11
Ten fragment zajmuje bardzo wysoką pozycję na liście rzeczy, których wstydzę się pokazać programistom spoza C #.
Traubenfuchs
99
Dlaczego do diabła nie możemy tak po prostu zrobić data.Split("xx")?
mcont
122

Istnieje przeciążenie Split, które wymaga ciągów.

"THExxQUICKxxBROWNxxFOX".Split(new [] { "xx" }, StringSplitOptions.None);

Możesz użyć jednego z tych StringSplitOptions

  • Brak - zwracana wartość obejmuje elementy tablicy zawierające pusty ciąg
  • RemoveEmptyEntries - Zwracana wartość nie obejmuje elementów tablicy zawierających pusty ciąg

Więc jeśli ciąg jest „THExxQUICKxxxxBROWNxxFOX”, StringSplitOptions.Nonezwróci pusty wpis w tablicy dla części „xxxx”, podczas gdy StringSplitOptions.RemoveEmptyEntriesnie.

Greg
źródło
73
Regex.Split(string, "xx")

zwykle tak robię.


Oczywiście potrzebujesz:

using System.Text.RegularExpressions;

lub:

System.Text.RegularExpressions.Regex.Split(string, "xx")

ale znowu potrzebuję tej biblioteki przez cały czas.

Piotr
źródło
13
@Brandon: Chociaż zwykle ostrzegam przed przedwczesną optymalizacją, powinieneś zdawać sobie sprawę, że a RegEx.Splitjest nieco bardziej kosztowne niż proste String.Splitze względu na narzut wyrażeń regularnych.
Adam Robinson
9
Jeśli chcesz podzielić na dowolny ciąg, użyj Regex.Escapego najpierw, spowoduje to uniknięcie meta-znaków wyrażenia regularnego.
Richard
jedną z kluczowych korzyści, które mogą się opłacić narzutem, jest możliwość zapewnienia ustawienia porównywania ciągów
Timur Sadykov
47

Jest w tym przeciążenie String.Split :

"THExxQUICKxxBROWNxxFOX".Split(new [] {"xx"}, StringSplitOptions.None);
Bruno Conde
źródło
1
Jedyna odpowiedź, która usuwa niepotrzebną deklarację typu tablicy.
wonea
25

Zasadniczo lubię używać własnego rozszerzenia:

string data = "THExxQUICKxxBROWNxxFOX";
var dataspt = data.Split("xx");
//>THE  QUICK  BROWN  FOX 


//the extension class must be declared as static
public static class StringExtension
{   
    public static string[] Split(this string str, string splitter)
    {
        return str.Split(new[] { splitter }, StringSplitOptions.None);
    }
}

Doprowadzi to jednak do wyjątku, jeśli Microsoft zdecyduje się uwzględnić to przeciążenie metody w późniejszych wersjach. Jest to również prawdopodobny powód, dla którego Microsoft nie uwzględnił w międzyczasie tej metody: przynajmniej jedna firma, w której pracowałem, zastosowała takie rozszerzenie we wszystkich swoich projektach C #.

Może być również możliwe warunkowe zdefiniowanie metody w czasie wykonywania, jeśli nie istnieje.

Lorenz Lo Sauer
źródło
4
Alternatywnie, zastosowanie params string[] splitterjako drugi parametr i zmiany new[] {splitter}do splitterobsługi wielu ograniczników.
Matthew Strawbridge
10

Wszystkie poprzednie odpowiedzi są poprawne. Idę o krok dalej i sprawiam, że C # działa dla mnie, definiując metodę rozszerzenia String:

public static class Extensions
{
    public static string[] Split(this string toSplit, string splitOn) {
        return toSplit.Split(new string[] { splitOn }, StringSplitOptions.None);
    }
}

W ten sposób mogę nazwać go dowolnym ciągiem w prosty sposób, którego naiwnie oczekiwałem przy pierwszej próbie:

"a big long string with stuff to split on".Split("g str");
argyle
źródło
7
string data = "THExxQUICKxxBROWNxxFOX";

return data.Replace("xx","|").Split('|');

Po prostu ostrożnie wybierz zamień znak (wybierz taki, który prawdopodobnie nie będzie już obecny w ciągu)!

Szkopuł
źródło
2
@MasoudHosseini: Proszę przeczytać pełną odpowiedź; jest już zastrzeżenie.
SNag
3
@kobe: Ponieważ to straszny hack.
Overv
3
Działa dobrze, ale jest niebezpieczny dla metod ogólnych
Kaizonaro
5
Wyjaśnienia typu „To straszny hack” lub „zła odpowiedź” nie są pomocne. To po prostu opinia bez wyjaśnienia. Zamiast tego stwierdzenie: „Nie ma potrzeby, aby skanować ciąg w poszukiwaniu zamienników, a następnie skanować w poszukiwaniu podzielonych znaków, ponieważ prowadzi to do słabej wydajności”. byłoby lepszym sposobem na wyjaśnienie siebie. Zbyt wielu programistów działa w ten sposób. :(
Matt Ruwe,
1
Co jeśli ciąg zawiera |już znak, z tego powodu uważam, że korzystanie z niego jest niebezpieczne.
amd
-1

Jest to również łatwe:

string data = "THExxQUICKxxBROWNxxFOX";
string[] arr = data.Split("xx".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
użytkownik890255
źródło
1
Ale to również podzieliłoby się "THExQUICK"tam, gdzie nie chcemy, aby zostało podzielone
Rafalon
Dzięki Rafalon: tak, Greg's jest najlepszą odpowiedzią: data.Split (new string [] {"xx"}, StringSplitOptions.RemoveEmptyEntries)
user890255
-4

Najprostszym sposobem jest użycie String.Replace:

string myString = "THExxQUICKxxBROWNxxFOX";
mystring = mystring.Replace("xx", ", ");

Lub prościej:

string myString = "THExxQUICKxxBROWNxxFOX".Replace("xx", ", ");
użytkownik3458227
źródło
3
W tej chwili nie zwróci tablicy (jak pyta pytanie), tylko ciąg znaków z przecinkami tam, gdzie xxbyły.
Arj
I nie tylko, że jeśli łańcuch zawiera dodatkowe przecinki, nie będziesz w stanie poprawnie rozdzielić słów.
user3658298