Удалить последнее вхождение непоследовательного, дублирующего слова / фазы в строке PHP - PullRequest
0 голосов
/ 09 ноября 2018

Хорошо, я пытался выяснить это какое-то время, но я не могу понять это правильно.Мне нужно удалить последний вхождение непоследовательного, дублирующего слова / фразы из END строки.Например, я хочу, чтобы

Love in My Antonia Love in

и

Love in My Antonia Love

стали

Love in My Antonia

Я пробовал множество моделей без успеха.Самое близкое, что я получил к успеху, это:

 preg_replace('/\b(\w{2,})\b(?=.*?\\1)\W*/', ''

, который удаляет первое вхождение (а не последнее), рендеринг:

 in My Antonia Love (ORIGINAL: "Love in My Antonia Love")

и

 My Antonia Love in (ORIGINAL: "Love in My Antonia Love in")

Пожалуйста, помогите!:)

ОБНОВЛЕНИЕ (9 ноября, 2:00 вечера, по тихоокеанскому времени): Я должен был пояснить, что - если это вообще возможно - я бы хотел, чтобы решение оставалось в простом, компактном формате из 1 строки, который я показал в моем примере:

preg_replace('/\b(\w{2,})\b(?=.*?\\1)\W*/', ''

Мой пример уже работает почти идеально, за исключением того, что он удаляет совпадение first вместо last .Я надеялся, что кто-то может скромно манипулировать моим существующим кодом, чтобы он удалял последнее совпадение (в конце строки) вместо первого вхождения.Это сложнее, чем я думал?

Ранее я придумал версию, которая находит два последовательных, повторяющихся слова / фразы в любом месте строки и заменяет их одним:

preg_replace('~\b([\S \w]{3,})\K\b(?:\s*\1)+~', '', 

Это делает "пиццу пиццей" превращаться в "пиццу" и "я ходил"в магазин я ходил в магазин "стал" я ходил в магазин ".Это здорово, и я уже включил это решение.Теперь, во-вторых, мне нужно, чтобы «Пицца - лучшая пицца», чтобы стать «Пицца - лучшая».Точно так же, «Овчарки - замечательные домашние животные», должно стать «Овчарки - замечательные домашние животные».Так что, в принципе, не имеет значения, где в строке появляется первое вхождение;все, что имеет значение, - это то, что вхождение в END OF STRING удаляется.Надеюсь, это принесет больше ясности.

Ответы [ 3 ]

0 голосов
/ 09 ноября 2018

Сначала нужно найти самую длинную дублированную подстроку, а затем удалить ее из конца строки темы. Это можно сделать, используя preg_match_all для поиска без учета регистра, а затем preg_replace для их пропуска:

$str = 'Love in My Antonia Love in';
preg_match_all('~(\b\w++(?> \w++)*)(?=.*?\b\1)~i', $str, $matches);
$array = array_unique(array_map('strtolower', $matches[1]));
foreach ($array as $value) {
    $str = preg_replace("~^.*\K(?<!\s)\s*\b$value~i", '', $str);
}
echo trim($str); // Love in My Antonia

Смотрите демо здесь

0 голосов
/ 10 ноября 2018

Вот, пожалуйста:

$s = preg_replace('/^\b([\w ]+)(.*?)\b(\1)$/i', '\\1\\2', $s);

Тест:

$s = "Love in My Antonia Love in";
$s1 = "Love in My Antonia Love";
$s2 = "Love in My Antonia Love Not On End";

echo "Original:\n$s\n";
echo preg_replace('/^\b([\w ]+)(.*?)\b(\1)$/i', '\\1\\2', $s);
echo "\n";
echo "Original:\n$s1\n";
echo preg_replace('/^\b([\w ]+)(.*?)\b(\1)$/i', '\\1\\2', $s1);
echo "\n";
echo "Original:\n$s2\n";
echo preg_replace('/^\b([\w ]+)(.*?)\b(\1)$/i', '\\1\\2', $s2);

Выход:

ZC-MGMT-04:~ jv$ php -q c.php
Original:
Love in My Antonia Love in
Love in My Antonia
Original:
Love in My Antonia Love
Love in My Antonia
Original:
Love in My Antonia Love Not On End
Love in My Antonia Love Not On End

====

UPDATE:

Джейсон предлагает немного обновить адрес в конце слова:

preg_replace('/^\b([\w ]+)(.*?)\b\b(\1)(\'s)*\b$/i', '\\1\\2')
0 голосов
/ 09 ноября 2018

Вы можете подойти к этому без регулярных выражений, разделив предложение на составные слова, а затем вручную проверив последние два слова:

$input = "Love in My Antonia Love in";
$words = preg_split("/\s+/", $input);
$last = $words[count($words)-1];
$pattern = "/^(?=.*\b" . $last . "\b.*\b" . $last . "\b).*/";
if ($words[count($words) - 1] != $words[count($words) - 2] &&
    preg_match($pattern, $input, $match)) {
    array_pop($words);
}
$output = implode(" ", $words);
echo $input . "\n" . $output;

Love in My Antonia Love in
Love in My Antonia Love
...