Я пытаюсь решить wordEnds
from codingbat.com с помощью regex.
Учитывая строку и непустую строку слова, верните строку, состоящую из каждого char, непосредственно перед и сразу после каждого появления слова в строке. Игнорировать случаи, когда char нет или после слова, а char может быть дважды включен, если он находится между двумя словами.
wordEnds("abcXY123XYijk", "XY") → "c13i" wordEnds("XY123XY", "XY") → "13" wordEnds("XY1XY", "XY") → "11" wordEnds("XYXY", "XY") → "XY"
Это самое простое, поскольку я могу сделать это с моим текущим знанием регулярного выражения:
public String wordEnds(String str, String word) {
return str.replaceAll(
".*?(?=word)(?<=(.|^))word(?=(.|$))|.+"
.replace("word", java.util.regex.Pattern.quote(word)),
"$1$2"
);
}
replace
используется для размещения в фактической строке word
в шаблоне для удобочитаемости. Pattern.quote
не обязательно передавать свои тесты, но я думаю, что это необходимо для правильного решения на основе регулярных выражений.
Регулярное выражение имеет две основные части:
- Если после сопоставления как можно большего количества символов "
.*?
",word
все еще можно найти "(?=word)
", затем найдите, чтобы захватить любой символ, предшествующий ему "(?<=(.|^))
", совпадение "word
", и посмотрите, чтобы захватить любой символ после него "(?=(.|$))
".- Исходный тест "if" гарантирует, что атомный lookbehind захватывает, только если есть
word
- Использование lookahead для захвата следующего символа не потребляет его, поэтому его можно использовать как часть дальнейшего сопоставления
- Исходный тест "if" гарантирует, что атомный lookbehind захватывает, только если есть
- В противном случае сопоставьте то, что осталось "
|.+
"- Группы 1 и 2 будут записывать пустые строки
Я думаю, что это работает во всех случаях, но это, очевидно, довольно сложно. Мне просто интересно, могут ли другие предложить более простое регулярное выражение для этого.
Примечание. Я не ищу решение с помощью indexOf
и цикла. Я хочу решение replaceAll
на основе регулярного выражения. Я также нуждаюсь в рабочем регулярном выражении, которое передает все тесты кодирования.
Мне удалось уменьшить появление word
внутри шаблона только до одного.
".+?(?<=(^|.)word)(?=(.?))|.+"
Я все еще смотрю, можно ли это упростить, но у меня также есть другой вопрос:
- С помощью этого последнего шаблона я упростил
.|$
только.?
, но если я попытался упростить^|.
до.?
, это не сработает. Почему это?