PHP中的近似字符串匹配

时间:2019-01-29 10:15:34

标签: php preg-match-all string-comparison

假设我需要比较两个变量

$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 因此preg_match检查应该将$ team和$ team2视为相同(非常相似)? 例如,在上面的preg_match中,由于$ team中的方括号(),有4个字符错误,我可以允许这些错误传递给preg_match吗?

可能还有其他情况,例如$ team2可能...

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

等等..各种情况,这仅是示例。所有这些都应该与$ team匹配,我该怎么做才能在php中执行此近似字符串匹配?

谢谢

3 个答案:

答案 0 :(得分:1)

编辑:看到有关使用same_text的注释后,我删除了此答案,但是我在测试字符串上的实验在team1和team2之间仅给出了78%。这可能足够好,但是我认为替代方法可能会有用。

值得注意的是,除非您开始使用各种伪AI东西,否则您永远都不会获得人类认可的东西。从事物的外观来看,您可以“确定”每个单词至少会拼写相同。我建议将字符串通过任何非字母数字的字符拆分成一个数组,然后对该数组进行排序,并检查它是否与每个团队的“主”匹配。

它看起来像(未经测试-$ pattern可能需要更多工作)

jxz.smith

当然,您可以添加逻辑来解决发现的其他问题...

答案 1 :(得分:1)

您可以使用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

答案 2 :(得分:1)

另一种方法是在多爆炸阵列上使用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