@Kak_B_CTapou_Cka3ke

Как проверить значения массива на схожесть?

Предположим, в массиве есть значения, которые сильно похожи, но из-за мелких опечаток являются разными:
Продам клинок демона +6 / Солнцеликий плащ +2 тьма
Продам клинок демона +6, Солнцеликий плащщ +2тьма
Акция! Продам клинок демона +6, Солнцеликий плащ +2тьма

как оставить только одно (любое) значение, например, по некоторому количеству повторяющихся букв или слов?
Как правило расхождения небольшие, скорее всего трёх следующих друг за другом слов будет достаточно.
Спасибо за любую помощь!
  • Вопрос задан
  • 113 просмотров
Решения вопроса 2
@dzhebrak
Еще одно решение - вычислить расстояние Левенштейна между строками https://www.php.net/manual/ru/function.levenshtein.php

Расстояние Левенштейна - это минимальное количество вставок, замен и удалений символов, необходимое для преобразования str1 в str2. Сложность алгоритма равна O(m*n), где n и m - длины строк str1 и str2 (неплохо по сравнению с similar_text(), имеющей сложность O(max(n,m)**3), но все же довольно много).

echo(levenshtein('abcdefg', 'amcdehg'));
Если расстояние между строками равно 2, значит нужно вставить, заменить или удалить 2 символа, соответственно строки похожи.

Функция для работы с русским языком: https://gist.github.com/shankao/b0d92e15c65852fda481

Пример:
$lines = [
  'Продам клинок демона +6 / Солнцеликий плащ +2 тьма',
  'Продам клинок демона +6, Солнцеликий плащщ +2тьма',
  'Акция! Продам клинок демона +6, Солнцеликий плащ +2тьма',
  'Продам клинок ангела +3, Луноликая куртка +4свет',
  'Продам клинок ангелла +3, Луноликая куртка +4свет',
  'Акция ! Продам клинок ангела +3, Луноликая куртка +4свет',
  'тест акции',
  'проверка демона',
  'проверка ангела',
];

$res = [];
$allSimilar = [];

foreach ($lines as $line) {
    $similarLines = [];

    if(in_array($line, $allSimilar)) {
        continue;
    }

    foreach ($lines as $line1) {
        $lev = mb_levenshtein($line, $line1);
        $maxDistance = (int)(0.2 * max(mb_strlen($line), mb_strlen($line1)));

        if($lev <= $maxDistance) {
            $similarLines[] = $line1;
            $allSimilar[] = $line1;
        }
    }

    $res[$line] = $similarLines;
}

print_r($res);

Похожими считаются фразы, которые отличаются менее чем на 20% их длины.
Ответ написан
Комментировать
meowto16
@meowto16
Делаю штуки
Можно попробовать сравнивать похожесть строк https://www.php.net/manual/ru/function.similar-text.php, и если % схожести больше n-значения убирать одно из них
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы