Подтвердить что ты не робот

Извлечение пар слов с помощью String.split()

Дано:

String input = "one two three four five six seven";

Есть ли регулярное выражение, которое работает с String.split(), чтобы захватить (до) два слова за раз, например:

String[] pairs = input.split("some regex");
System.out.println(Arrays.toString(pairs));

приводит к следующему:

[one two, three four, five six, seven]

Этот вопрос касается разделенного регулярного выражения. Речь идет не о том, чтобы "найти работу" или другое "сделать работу по-другому".

4b9b3361

Ответ 1

В настоящее время (включая Java 8) это можно сделать с помощью split(), но в реальном мире этот подход не используется, поскольку он выглядит так, как будто он основан на ошибке (look-behind в Java должен иметь очевидная максимальная длина, но в этом решении используется \w+, который не соблюдает это ограничение). Вместо этого используйте классы Pattern и Matcher, чтобы избежать чрезмерного компрометации thins и обслуживания ада, поскольку это поведение может измениться в следующих версиях Java или в Java-подобных средах, таких как Android.


Это то, что вы ищете?
(вы можете заменить \\w на \\S, чтобы включить все непространственные символы, но в этом примере я оставлю \\w, так как легче читать регулярное выражение с помощью \\w\\s, а затем \\S\\s)суб >

String input = "one two three four five six seven";
String[] pairs = input.split("(?<!\\G\\w+)\\s");
System.out.println(Arrays.toString(pairs));

выход:

[one two, three four, five six, seven]

\G - предыдущее совпадение, (?<!regex) - отрицательный lookbehind.

В split мы пытаемся

  • найти пробелы → \\S
  • которые не прогнозируются → (?<!negativeLookBehind)
  • некоторым словом → \\w+
  • с ранее сопоставленным (пробелом) → \\G
  • перед этим → \\G\\w+.

Только путаница, с которой я столкнулся, заключалась в том, как она будет работать для первого пространства, так как мы хотим, чтобы это пространство было проигнорировано. Важная информация заключается в том, что \\G при запуске соответствует началу строки ^.

Итак, перед тем как первое итерационное регулярное выражение будет выглядеть как (?<!^\\w+), а так как первое пространство do имеет ^\\w+ раньше, оно не может быть совпадением для split. Следующий пробел не будет иметь этой проблемы, поэтому он будет согласован, и информация об этом (например, его позиция в input String) будет сохранена в \\G и использована позже в следующем негативном образе.

Итак, для 3-го пространства регулярное выражение будет проверять, есть ли ранее сопоставленное пространство \\G и слово \\w+ перед ним. Поскольку результат этого теста будет положительным, отрицательный внешний вид не примет его, поэтому это пространство не будет согласовано, но 4-е пространство не будет иметь эту проблему, потому что пространство до него не будет таким же, как в \\G (оно будет иметь разную позицию в input String).


Также, если кто-то хочет разделить на let, скажем, каждое третье пространство, вы можете использовать эту форму (на основе @maybeWeCouldStealAVan ответ, который был удален, когда я разместил этот фрагмент ответа)

input.split("(?<=\\G\\w{1,100}\\s\\w{1,100}\\s\\w{1,100})\\s")

Вместо 100 вы можете использовать какое-то большее значение, которое будет по меньшей мере размером с длиной самого длинного слова в String.


Я только заметил, что мы можем использовать + вместо {1,maxWordLength}, если мы хотим разделить с каждым нечетным числом, как каждый третий, пятый, седьмой, например

String data = "0,0,1,2,4,5,3,4,6,1,3,3,4,5,1,1";
String[] array = data.split("(?<=\\G\\d+,\\d+,\\d+,\\d+,\\d+),");//every 5th comma 

Ответ 2

Это будет работать, но максимальная длина слова должна быть задана заранее:

String input = "one two three four five six seven eight nine ten eleven";
String[] pairs = input.split("(?<=\\G\\S{1,30}\\s\\S{1,30})\\s");
System.out.println(Arrays.toString(pairs));

Мне нравится, что Pshemo лучше отвечает, сокращается и может использоваться на произвольных длинах слов, но это (как указывает @Pshemo) имеет то преимущество, что оно может быть адаптировано к группам из более чем двух слов.

Ответ 3

это сработало для меня (\w+\s*){2}\K\s пример здесь

  • обязательное слово, за которым следует дополнительное пространство (\w+\s*)
  • повторяется два раза {2}
  • игнорировать ранее сопоставленные символы \K
  • требуемое пространство \s

Ответ 4

Вы можете попробовать следующее:

[a-z]+\s[a-z]+

Обновлено:

([a-z]+\s[a-z]+)|[a-z]+

enter image description here

Обновлено:

 String pattern = "([a-z]+\\s[a-z]+)|[a-z]+";
 String input = "one two three four five six seven";

 Pattern splitter = Pattern.compile(pattern);
 String[] results = splitter.split(input);

 for (String pair : results) {
 System.out.println("Output = \"" + pair + "\"");