Приблизительное совпадение строк в php - PullRequest
0 голосов
/ 29 января 2019

предположим, что мне нужно сравнить две переменные

$team="Benfica(U23):Vitoria Guimaraes(U23)";

и

$team2="Benfica U23:Vitoria Guimaraes U23";

Для моей точки зрения $ team и $ team2 должны совпадать, на самом деле это одно и то же устройство, только изменениеU23 с (U23).

Однако preg_match не такой умный, как человек, поэтому, если я использую

if (preg_match("/$team/",$team2)) {
echo "they match";
}

, они, конечно, не совпадают.Как я могу сделать приблизительный preg_match, чтобы проверка $ team и $ team2 считались одинаковыми (очень похожими) при проверке preg_match?Например, в preg_match выше есть 4 ошибки символов из-за скобок () в $ team, могу ли я разрешить этим ошибкам передавать preg_match?.

Могут быть и другие ситуации, например, $ team2 может быть ...

$team2="U23 Benfica:Vitoria Guimaraes";
$team2="Benfica (U23):Vitoria Guimaraes U23";
$team2="Benfica U23:Vitoria Guimaraes(U23)";

и т. Д. Различные ситуации, это только пример.Все они должны совпадать с $ team, что я могу сделать, чтобы выполнить это приблизительное сопоставление строк в php?

Спасибо

Ответы [ 3 ]

0 голосов
/ 29 января 2019

Вы можете использовать levenshtein($team, $team2), чтобы иметь число, представляющее, насколько отличаются строки, а затем определить пороговое значение, чтобы решить, насколько вы хотите быть терпимым.

if (levenshtein($team, $team2) < 3) {
    echo "string are similar";
} else {
    echo "string are not similar";
}

http://php.net/manual/en/function.levenshtein.php

0 голосов
/ 29 января 2019

Другой метод - использовать array_intersect для многократно взорванного массива.

Удалите () и замените пробел.
Разнесите пробел и двоеточие и отфильтруйте все пустое.

Используйте array_intersect, чтобы увидеть, сколько равных предметов существует, и посмотреть, соответствует ли это количеству уникальных предметов.

Это, конечно, можно откалибровать, если количество находится в пределах поля, если вы хотитечто.

$team1="U23 Benfica:Vitoria Guimaraes";
$team2="Benfica (U23):Vitoria Guimaraes U23";
var_dump(match($team1, $team2));

$team1="U23 Benfica:Vitoria Guimaraes";
$team2="Benfica U23:Vitoria Guimaraes(U23)";
var_dump(match($team1, $team2));

$team1="Benfica U23:Vitoria Guimaraes(U23)";
$team2="Benfica (U23):Vitoria Guimaraes U23";
var_dump(match($team1, $team2));

function match($s1, $s2){
    // remove the ( and ) and replace with space
    $s1 = str_replace(["(",")"], " ", $s1); 
    $s2 = str_replace(["(",")"], " ", $s2);

    $delimiters = [" ", ":"]; // add more delimiters if needed
    // explode on $delimiters and remove empty values
    $arr1 = array_filter(multiexplode($delimiters,$s1)); 
    $arr2 = array_filter(multiexplode($delimiters,$s2));
//var_dump($arr1, $arr2);

    // How many items is equal between $arr1 and $arr2
    $intersect = count(array_unique(array_intersect($arr1, $arr2)));

    // is the count of equal items the same as the count of items in the strings
    if($intersect == count(array_unique($arr1)) && $intersect == count(array_unique($arr2))){
        return true;
    }else{
        return false;
    }

}

// From PHP manual explode
function multiexplode ($delimiters,$string) {

    $ready = str_replace($delimiters, $delimiters[0], $string);
    $launch = explode($delimiters[0], $ready);
    return  $launch;
}

Возвращает:

bool(true)
bool(true)
bool(true)

https://3v4l.org/MY7j7

0 голосов
/ 29 января 2019

Редактировать: я удалил этот ответ, увидев комментарий об использовании Similar_text, но мои эксперименты с тестовыми строками дали только 78% между team1 и team2.Это может быть достаточно хорошо, но я подумал, что альтернатива может быть полезной.

Стоит отметить, что, если вы не начнете использовать все виды псевдо-ИИ, вы никогда не получите ничего похожего на человеческое признание.Судя по всему, вы «уверены», что каждое слово будет написано по крайней мере одинаково.Я бы предложил разделить строку любым не алфавитно-цифровым символом в массиве, затем отсортировать массив и проверить его на соответствие «master» для каждой команды.

Это будет выглядеть примерно так (это не проверено -$ pattern может потребоваться больше работы)

<?php
  $teamString = "Benfica (U23):Vitoria Guimaraes U23";
  $masterArray = ['Benfica','Guimares','U23','Vitoria'];
  $pattern = '/[^a-zA-Z\d]/';
  $teamArray = preg_split( $pattern, $teamString );
  sort($teamArray);
  $interArray = array_unique($teamArray); //to remove duplicate U23
  $finalArray = array_filter($interArray, function($k) {
    return (preg_replace('/\s+/', '', $k) != ''); //to get rid of whitespace
  });
  //...compare $finalArray with $masterArray

Конечно, вы можете добавить логику для решения других задач по мере их обнаружения ...

...