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.