Почему "разделение" на пустую строку возвращает непустой массив?

Разделение на пустую строку возвращает массив размером 1:

scala> "".split(',')
res1: Array[String] = Array("")

Учтите, что это возвращает пустой массив:

scala> ",,,,".split(',')
res2: Array[String] = Array()

Пожалуйста, объясните:)

Ответ 1

По той же причине, что

",test" split ','

и

",test," split ','

вернет массив размера 2. Все, прежде чем первое совпадение будет возвращено в качестве первого элемента.

Ответ 2

Если вы разделите оранжевое нулевое время, у вас будет ровно одна часть - оранжевая.

Ответ 3

Разделение пустой строки возвращает пустую строку в качестве первого элемента. Если разделитель не найден в целевой строке, вы получите массив размером 1, который содержит исходную строку, даже если она пуста.

Ответ 4

Методы разделения Java и Scala работают в два этапа, например:

  • Сначала разделите строку по разделителю. Естественным следствием является то, что если строка не содержит разделитель, возвращается массив синглтона, содержащий только входную строку,
  • Во-вторых, удалите все крайние правые пустые строки. По этой причине ",,".split(",") возвращает пустой массив.

Согласно этому результат "".split(",") должен быть пустым массивом из-за второго шага, верно?

Должно. К сожалению, это искусственно введенный угловой корпус. И это плохо, но, по крайней мере, это java.util.regex.Pattern в java.util.regex.Pattern, если вы не забываете взглянуть на документацию:

Для n == 0 результат такой же, как для n <0, за исключением того, что завершающие пустые строки возвращаться не будут. (Обратите внимание, что случай, когда сам ввод является пустой строкой, является особым, как описано выше, и параметр limit там не применяется.)

Решение 1. Всегда передавайте -1 в качестве второго параметра.

Итак, я советую вам всегда передавать n == -1 в качестве второго параметра (это пропустит второй шаг выше), если вы не знаете, чего конкретно хотите достичь/вы уверены, что пустая строка - это не то, что ваша программа получит в качестве входа.

Решение 2. Используйте класс Guava Splitter

Если вы уже используете 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"

Ответ 5

"a".split(",")"a" следовательно "".split(",")""

Ответ 6

Во всех языках программирования я знаю, что пустая строка по-прежнему является действительной строкой. Таким образом, разделение с использованием любого разделителя всегда будет возвращать один массив элементов, где этот элемент является пустой строкой. Если это был пустой (не пустой) String, это было бы другой проблемой.

Ответ 7

Это split поведение наследуется от Java, к лучшему или худшему...
Scala не переопределяет определение из примитива String.

Обратите внимание, что вы можете использовать аргумент 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.

Примечание. Метод split не был в Java с самого начала (он не в версии 1.0.2), но на самом деле существует менее 1,4 (например, см. JSR51 около 2002 г.). Я все еще расследую...

Непонятно, почему Java выбрала это в первую очередь (мое подозрение в том, что это изначально было недосмотр/ошибка в "краевом случае" ), но теперь безвозвратно запекается на этом языке, и поэтому он остается.

Ответ 8

Пустая строка не имеет специального статуса при разбиении строки. Вы можете использовать:

Some(str)
  .filter(_ != "")
  .map(_.split(","))
  .getOrElse(Array())

Ответ 9

Вы можете использовать следующее ниже, чтобы вернуть пустую строку.

String[] files = new String[0];