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



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



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


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



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


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

564   8  

8 ответов:

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

",test" split ','

и

",test," split ','

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

Если вы разделите апельсин ноль раз, у вас есть ровно один кусок - апельсин.

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

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

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

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

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

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

Решение 1: всегда возвращает -1 в качестве второго параметра

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

TL; DR: разделение пустой строки является искусственно введенный угловой корпус и документация предупреждает вас об этом. Всегда возвращает -1 в качестве второго параметра, чтобы избежать ошибок, если у вас есть веская причина.

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

если вы уже используете Guava в своем проекте, вы можете попробовать сплиттер (документация) класса. Он имеет очень богатый 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"

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

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

этой split поведение наследуется от Java, к лучшему или худшему...
Scala не переопределяет определение из 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.

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

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

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

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

Comments

    Ничего не найдено.