Ponadto wydaje się niespójne z zachowaniem obserwowanym, gdy ciąg zawiera tylko jedno wystąpienie separatora. W tym przypadku wynikiem jest faktycznie pusta tablica: ",". Split (","). Length == 0
LD.
Odpowiedzi:
37
Z tego samego powodu
",test" split ','
i
",test," split ','
zwróci tablicę o rozmiarze 2. Wszystko przed pierwszym dopasowaniem zostanie zwrócone jako pierwszy element.
Ale pomarańcza nie jest pusta (nie wiem, czy to właśnie mieli na myśli oluies), jest pomarańczowa. Może podzielić pomarańczę, która powinna tam być, ale jej nie ma, więc otrzymujesz jedną wartość: puste miejsce xD
Nick Rolando.
8
To jest głęboka rozmowa.
31
Ta metafora ma sens "orange".split(','), ale nie jest oczywiście odpowiednia do dzielenia pustych ciągów. Jeśli podzielę brak pomarańczy zero razy, nadal nie mam pomarańczy; Czy przedstawiamy to jako pustą listę bez pomarańczy, listę dokładnie jednego bez pomarańczy, listę dwunastu bez pomarańczy, czy co? Nie jest to kwestia tego, z czym skończymy, ale jak to przedstawiamy.
Matchu
1
Ale jeśli podzielisz nieistniejącą książkę według stron, nic nie otrzymasz.
SMUsamaShah,
49
Metody podziału Java i Scala działają w dwóch krokach:
Najpierw podziel ciąg przez separator. Naturalną konsekwencją jest to, że jeśli ciąg nie zawiera separatora, zwracana jest tablica singleton zawierająca tylko ciąg wejściowy,
Po drugie, usuń wszystkie skrajne prawe puste ciągi. To jest powód, dla którego ",,,".split(",")zwraca pustą tablicę.
Zgodnie z tym, wynik "".split(",")powinien być pustą tablicą z powodu drugiego kroku, prawda?
Powinno. Niestety jest to sztucznie wprowadzona obudowa narożna. I że jest źle, ale przynajmniej jest udokumentowana w java.util.regex.Pattern, jeśli pamiętać, aby zapoznać się z dokumentacją:
Dla n == 0 wynik jest taki, jak dla n <0, z wyjątkiem końcowych pustych ciągów, które nie zostaną zwrócone. (Zauważ, że przypadek, w którym dane wejściowe jest samym pustym ciągiem, jest specjalny, jak opisano powyżej, a parametr limit nie ma tam zastosowania).
Rozwiązanie 1: Zawsze przekazuj -1 jako drugi parametr
Dlatego radzę zawsze podawać n == -1jako drugi parametr (spowoduje to pominięcie kroku drugiego powyżej), chyba że dokładnie wiesz, co chcesz osiągnąć / jesteś pewien, że pusty łańcuch nie jest czymś, co Twój program otrzymałby jako dane wejściowe.
Rozwiązanie 2: Użyj klasy Guava Splitter
Jeśli używasz już guawy w swoim projekcie, możesz wypróbować klasę Splitter (dokumentacja) . Ma bardzo bogate API i sprawia, że kod jest bardzo łatwy do zrozumienia.
+1, jest to jedyna odpowiedź, która faktycznie cytuje dokumentację i wskazuje, że jest ona niespójna. Jednak nie znalazłem podświetlonej części komentarza w moim JavaDoc.
Yogu
Znalazłem go w java.util.regex.Pattern, ale wydaje się, że w większości zniknął. W chwili pisania tego tekstu na pewno był obecny w oficjalnym drzewie źródłowym OpenJDK jako javadoc. android.googlesource.com/platform/libcore/+/… Może powinniśmy zgłosić błąd?
Rok Kralj
Byłoby dobrym pomysłem zgłoszenie błędu - zachowanie na pewno nie zostanie zmienione, ale powinno być przynajmniej udokumentowane.
Yogu
@RokKralj Android nie korzystał z biblioteki OpenJDK, ale zamiast tego był oparty na Apache Harmony, więc może szukasz w złym miejscu?
lxgr
1
"".split (",", n)generuje jednoelementową tablicę dla n in (-1, 0, 1) z Oracle JDK 8. Byłoby miło otrzymać tylko listę niepustych tokenów - zgadnij, że może być konieczne pełne wyrażenie regularne (coś w rodzaju "[^,\\s]+[^,]*[^,\\s]*").
simon.watts
40
Dzielenie pustego ciągu zwraca pusty ciąg jako pierwszy element. Jeśli w ciągu docelowym nie zostanie znaleziony separator, otrzymasz tablicę o rozmiarze 1, która zawiera oryginalny ciąg, nawet jeśli jest on pusty.
Źle. Split usuwa wszystkie skrajne prawe puste ciągi, dlatego wynik powinien być pustą tablicą. Zobacz moją odpowiedź. ",".split(",")zwraca pustą tablicę.
Źle. Split usuwa wszystkie skrajne prawe puste ciągi, dlatego wynik powinien być pustą tablicą. Zobacz moją odpowiedź. ",".split(",")zwraca pustą tablicę.
Rok Kralj
5
Wiem, że we wszystkich językach programowania pusty ciąg jest nadal prawidłowym ciągiem. Zatem podział za pomocą dowolnego separatora zawsze zwróci tablicę pojedynczego elementu, w której ten element jest pustym ciągiem. Gdyby był to ciąg pusty (nie pusty), byłby to inny problem.
Myślę, że jest to funkcja biblioteczna, a nie część języka. Na przykład w google guava można pominąć puste ciągi znaków. > Iterowalne <String> pieces = com.google.common.base.Splitter.on (','). OmitEmptyStrings (). Split ("");
oluies
2
To splitzachowanie jest dziedziczone po Javie, na dobre lub na złe ...
Scala nie zastępuje definicji z Stringpierwotnego.
Parametr limit określa, ile razy wzór jest stosowany, a zatem wpływa na długość wynikowej tablicy. Jeśli limit n jest większy od zera, to wzorzec zostanie zastosowany najwyżej n - 1 razy, długość tablicy nie będzie większa niż n, a ostatni wpis tablicy będzie zawierał wszystkie dane wejściowe poza ostatnim dopasowanym ogranicznikiem. Jeśli n jest niedodatnie, wzór zostanie zastosowany tyle razy, ile to możliwe, a tablica może mieć dowolną długość. Jeśli n wynosi zero, to wzór zostanie zastosowany tyle razy, ile to możliwe, tablica może mieć dowolną długość, a końcowe puste ciągi zostaną odrzucone.
tzn. możesz ustawić, limit=-1aby uzyskać zachowanie (wszystkich?) innych języków:
Wydaje się, że dobrze wiadomo, że zachowanie Javy jest dość zagmatwane, ale:
Powyższe zachowanie można zaobserwować od co najmniej Java 5 do Java 8.
Podjęto próbę zmiany zachowania w celu zwrócenia pustej tablicy podczas dzielenia pustego łańcucha w JDK-6559590 . Jednak wkrótce został przywrócony w JDK-8028321, gdy powoduje regresję w różnych miejscach. Zmiana nigdy nie pojawia się w pierwszej wersji Java 8.
Uwaga: metoda podziału nie była w Javie od początku (nie ma jej w wersji 1.0.2 ), ale w rzeczywistości istnieje od co najmniej 1.4 (np. Patrz JSR51 około 2002). Wciąż prowadzę dochodzenie ...
Nie jest jasne, dlaczego Java wybrała to w pierwszej kolejności (podejrzewam, że pierwotnie był to przeoczenie / błąd w „skrajnym przypadku”), ale teraz nieodwołalnie wypalił się w języku i tak pozostaje .
Nie jestem pewien, czy to odpowiada na pytanie - chociaż może to być prawda w podanym tutaj przykładzie, nie pomaga to w przypadku pustego ciągu - "".split(",")nadal zwraca tablicę pojedynczego elementu, taką jak [""].
DaveyDaveDave
@DaveyDaveDave to oczekiwane zachowanie w każdym innym języku. „,,,” to dziwne / odmienne zachowanie w Scali i różni się od przypadku „”.
Andy Hayden,
0
Pusty łańcuch nie ma specjalnego statusu podczas dzielenia łańcucha. Możesz użyć:
Odpowiedzi:
Z tego samego powodu
i
zwróci tablicę o rozmiarze 2. Wszystko przed pierwszym dopasowaniem zostanie zwrócone jako pierwszy element.
źródło
"".split("wtf").length
zwraca 0. Tylko w JS to 1.: /"," split ","
zwraca tablicę 0?Jeśli podzielisz pomarańczę zero razy, masz dokładnie jedną część - pomarańczę.
źródło
"orange".split(',')
, ale nie jest oczywiście odpowiednia do dzielenia pustych ciągów. Jeśli podzielę brak pomarańczy zero razy, nadal nie mam pomarańczy; Czy przedstawiamy to jako pustą listę bez pomarańczy, listę dokładnie jednego bez pomarańczy, listę dwunastu bez pomarańczy, czy co? Nie jest to kwestia tego, z czym skończymy, ale jak to przedstawiamy.Metody podziału Java i Scala działają w dwóch krokach:
",,,".split(",")
zwraca pustą tablicę.Zgodnie z tym, wynik
"".split(",")
powinien być pustą tablicą z powodu drugiego kroku, prawda?Powinno. Niestety jest to sztucznie wprowadzona obudowa narożna. I że jest źle, ale przynajmniej jest udokumentowana w
java.util.regex.Pattern
, jeśli pamiętać, aby zapoznać się z dokumentacją:Rozwiązanie 1: Zawsze przekazuj -1 jako drugi parametr
Dlatego radzę zawsze podawać
n == -1
jako drugi parametr (spowoduje to pominięcie kroku drugiego powyżej), chyba że dokładnie wiesz, co chcesz osiągnąć / jesteś pewien, że pusty łańcuch nie jest czymś, co Twój program otrzymałby jako dane wejściowe.Rozwiązanie 2: Użyj klasy Guava Splitter
Jeśli używasz już guawy w swoim projekcie, możesz wypróbować klasę Splitter (dokumentacja) . Ma bardzo bogate API i sprawia, że kod jest bardzo łatwy do zrozumienia.
źródło
"".split (",", n)
generuje jednoelementową tablicę dla n in (-1, 0, 1) z Oracle JDK 8. Byłoby miło otrzymać tylko listę niepustych tokenów - zgadnij, że może być konieczne pełne wyrażenie regularne (coś w rodzaju"[^,\\s]+[^,]*[^,\\s]*"
).Dzielenie pustego ciągu zwraca pusty ciąg jako pierwszy element. Jeśli w ciągu docelowym nie zostanie znaleziony separator, otrzymasz tablicę o rozmiarze 1, która zawiera oryginalny ciąg, nawet jeśli jest on pusty.
źródło
",".split(",")
zwraca pustą tablicę."a".split(",")
->"a"
dlatego"".split(",")
->""
źródło
",".split(",")
zwraca pustą tablicę.Wiem, że we wszystkich językach programowania pusty ciąg jest nadal prawidłowym ciągiem. Zatem podział za pomocą dowolnego separatora zawsze zwróci tablicę pojedynczego elementu, w której ten element jest pustym ciągiem. Gdyby był to ciąg pusty (nie pusty), byłby to inny problem.
źródło
To
split
zachowanie jest dziedziczone po Javie, na dobre lub na złe ...Scala nie zastępuje definicji z
String
pierwotnego.Zauważ, że możesz użyć
limit
argumentu, aby zmodyfikować zachowanie :tzn. możesz ustawić,
limit=-1
aby uzyskać zachowanie (wszystkich?) innych języków:Wydaje się, że dobrze wiadomo, że zachowanie Javy jest dość zagmatwane, ale:
Uwaga: metoda podziału nie była w Javie od początku (nie ma jej w wersji 1.0.2 ), ale w rzeczywistości istnieje od co najmniej 1.4 (np. Patrz JSR51 około 2002). Wciąż prowadzę dochodzenie ...
Nie jest jasne, dlaczego Java wybrała to w pierwszej kolejności (podejrzewam, że pierwotnie był to przeoczenie / błąd w „skrajnym przypadku”), ale teraz nieodwołalnie wypalił się w języku i tak pozostaje .
źródło
"".split(",")
nadal zwraca tablicę pojedynczego elementu, taką jak[""]
.Pusty łańcuch nie ma specjalnego statusu podczas dzielenia łańcucha. Możesz użyć:
źródło