Podział na pusty ciąg zwraca tablicę o rozmiarze 1:
scala> "".split(',')
res1: Array[String] = Array("")
Weź pod uwagę, że zwraca to pustą tablicę:
scala> ",,,,".split(',')
res2: Array[String] = Array()
Proszę wytłumacz :)
Podział na pusty ciąg zwraca tablicę o rozmiarze 1:
scala> "".split(',')
res1: Array[String] = Array("")
Weź pod uwagę, że zwraca to pustą tablicę:
scala> ",,,,".split(',')
res2: Array[String] = Array()
Proszę wytłumacz :)
Odpowiedzi:
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.
"".split("wtf").lengthzwraca 0. Tylko w JS to 1.: /
"," split ","zwraca tablicę 0?
Jeśli podzielisz pomarańczę zero razy, masz dokładnie jedną część - pomarańczę.
"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ą:
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).
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.
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.
Splitter.on(".").split(".a.b.c.") // "", "a", "b", "c", ""
Splitter.on(",").omitEmptyStrings().split("a,,b,,c") // "a", "b", "c"
Splitter.on(CharMatcher.anyOf(",.")).split("a,b.c") // "a", "b", "c"
Splitter.onPattern("=>?").split("a=b=>c") // "a", "b", "c"
Splitter.on(",").limit(2).split("a,b,c") // "a", "b,c"
"".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.
",".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.
To splitzachowanie jest dziedziczone po Javie, na dobre lub na złe ...
Scala nie zastępuje definicji z Stringpierwotnego.
Zauważ, że możesz użyć limitargumentu, aby zmodyfikować zachowanie :
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:
@ ",a,,b,,".split(",")
res1: Array[String] = Array("", "a", "", "b")
@ ",a,,b,,".split(",", -1) // limit=-1
res2: Array[String] = Array("", "a", "", "b", "", "")
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 .
"".split(",")nadal zwraca tablicę pojedynczego elementu, taką jak [""].
Pusty łańcuch nie ma specjalnego statusu podczas dzielenia łańcucha. Możesz użyć:
Some(str)
.filter(_ != "")
.map(_.split(","))
.getOrElse(Array())