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


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);

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.


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.


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);

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.


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");


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)!


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);

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", ", ");

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.