Розділити на порожній рядок повертає масив розміром 1:
scala> "".split(',')
res1: Array[String] = Array("")
Враховуйте, що це повертає порожній масив:
scala> ",,,,".split(',')
res2: Array[String] = Array()
Будь ласка, поясніть :)
Розділити на порожній рядок повертає масив розміром 1:
scala> "".split(',')
res1: Array[String] = Array("")
Враховуйте, що це повертає порожній масив:
scala> ",,,,".split(',')
res2: Array[String] = Array()
Будь ласка, поясніть :)
Відповіді:
З тієї ж причини, що
",test" split ','
і
",test," split ','
поверне масив розміром 2. Усе до першого збігу повертається як перший елемент.
"".split("wtf").length
повертається 0. Тільки в JS це 1.: /
"," split ","
повертає масив 0?
Якщо ви розділите помаранчевий нуль разів, у вас рівно одна деталь - апельсин.
"orange".split(',')
, але очевидно не має значення для розбиття порожніх рядків. Якщо я розділив мою відсутність оранжевого нуля разів, у мене все одно немає жодного апельсина; чи ми представляємо це як порожній список не-апельсинів, список точно одного жодного апельсина, список дванадцяти не-апельсинів, чи що? Справа не в тому, до чого ми закінчуємо, а в тому, як ми це представляємо.
Методи розбиття Java та Scala діють у два етапи, як це:
",,,".split(",")
повертає порожній масив.Відповідно до цього, результат "".split(",")
другого кроку повинен бути порожнім масивом, так?
Це повинно. На жаль, це штучно запроваджений кутовий корпус. І це погано, але , по крайней мере , це документовано в java.util.regex.Pattern
, якщо ви пам'ятаєте , щоб поглянути на документацію:
Для n == 0 результат такий, як для n <0, за винятком того, що порожні рядки не будуть повернені. (Зауважте, що випадок, коли вхід сам по собі є порожнім рядком, є спеціальним, як описано вище, і граничний параметр там не застосовується.)
Отже, я раджу завжди переходити n == -1
як другий параметр (це буде пропускати другий крок вище), якщо ви конкретно не знаєте, чого хочете досягти / ви впевнені, що порожня рядок - це не те, що ваша програма отримала б як вхід.
Якщо ви вже використовуєте Guava у своєму проекті, ви можете спробувати клас Splitter (документація) . Він має дуже багатий API, і робить ваш код дуже легким для розуміння.
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)
створює масив одного елемента для n в (-1, 0, 1) за допомогою Oracle JDK 8. Було б непогано отримати список лише не порожніх лексем - здогадайтеся, може знадобитися повний регекс (щось подібне "[^,\\s]+[^,]*[^,\\s]*"
).
Розщеплення порожнього рядка повертає порожній рядок як перший елемент. Якщо в цільовому рядку не знайдено роздільника, ви отримаєте масив розміром 1, який містить оригінальну рядок, навіть якщо вона порожня.
",".split(",")
повертає порожній масив.
У всіх мовах програмування я знаю, що порожня рядок все ще є дійсною строкою. Таким чином, розбиття за допомогою будь-якого роздільника завжди буде повертати масив одного елемента, де цей елемент є порожнім рядком. Якщо це був нульовий (не порожній) рядок, то це була б інша проблема.
Така split
поведінка успадкована від Java, для кращого чи гіршого ...
Скала не перекриває визначення від String
примітивного.
Зауважте, що ви можете використовувати limit
аргумент для зміни поведінки :
Параметр limit контролює кількість застосованих шаблонів і, отже, впливає на довжину результуючого масиву. Якщо межа n перевищує нуль, тоді шаблон буде застосовано не більше n - 1 разів, довжина масиву буде не більше n, а останній запис масиву буде містити весь вхід за межі останнього відповідного роздільника. Якщо n не позитивно, шаблон буде застосовуватися якомога більше разів, і масив може мати будь-яку довжину. Якщо n дорівнює нулю, то візерунок буде застосований якомога більше разів, масив може мати будь-яку довжину, а слідні порожні рядки будуть відкинуті.
тобто ви можете встановити limit=-1
поведінку (усіх?) інших мов:
@ ",a,,b,,".split(",")
res1: Array[String] = Array("", "a", "", "b")
@ ",a,,b,,".split(",", -1) // limit=-1
res2: Array[String] = Array("", "a", "", "b", "", "")
Здається, добре відома поведінка Java дуже заплутано, але:
Поведінку вище можна спостерігати щонайменше від Java 5 до Java 8.
Була спроба змінити поведінку, щоб повернути порожній масив при розділенні порожнього рядка в JDK-6559590 . Однак він незабаром був повернений у JDK-8028321, коли він викликав регрес у різних місцях. Зміна ніколи не перетворює її на початковий випуск Java 8.
Примітка: Спосіб розділення не був у Java з самого початку (це не в 1.0.2 ), але насправді існує принаймні 1,4 (наприклад, див. JSR51 circa 2002). Я досі розслідую ...
Незрозуміло, чому Java обрала це в першу чергу (я підозрюю, що спочатку це був недогляд / помилка у "крайовому випадку"), але тепер безповоротно заграв у мову і так залишається .
"".split(",")
все одно повертає єдиний масив елементів на зразок [""]
.
Порожній рядок не має спеціального статусу під час розділення рядка. Ви можете використовувати:
Some(str)
.filter(_ != "")
.map(_.split(","))
.getOrElse(Array())