You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用PHP编写函数返回与查询字符串最相似的列表元素

解决PHP中字符串相似度匹配的问题

你遇到的问题是因为单纯使用similar_text()或levenshtein()这类字符级算法,无法识别「候选字符串包含完整查询关键词」的场景——这两个算法的核心逻辑分别是统计相似字符数、计算编辑距离,在你的例子里:

  • levenshtein()会认为"Belem"更接近,因为它转成"Belem Tower"只需要添加6个字符,编辑距离远小于第二个字符串需要删除17个字符的成本;
  • similar_text()如果只看返回的相似字符数,虽然第二个字符串的相似字符更多,但如果代码没结合百分比或权重逻辑,也可能误判。

要得到预期结果,需要结合子串匹配优先级或单词级相似度算法,以下是两种可行的实现方案:

方案一:子串匹配优先 + 字符相似度加权

先判断候选字符串是否包含完整查询(赋予高分优先级),再结合字符相似度计算最终得分,选出最高分的匹配项:

function findMostSimilar(string $query, array $candidates): string {
    $queryLower = strtolower($query);
    $bestMatch = $candidates[0];
    $highestScore = -1;

    foreach ($candidates as $candidate) {
        $candidateLower = strtolower($candidate);
        $score = 0;

        // 包含完整查询直接加高分,确保优先级
        if (str_contains($candidateLower, $queryLower)) {
            $score += 100;
        }

        // 叠加字符相似度百分比
        similar_text($queryLower, $candidateLower, $percent);
        $score += $percent;

        // 更新最佳匹配
        if ($score > $highestScore) {
            $highestScore = $score;
            $bestMatch = $candidate;
        }
    }

    return $bestMatch;
}

// 测试调用
$query = "Belem Tower";
$candidates = ["Belem", "Belem Tower, Lisbon, Portugal"];
echo findMostSimilar($query, $candidates); // 输出:Belem Tower, Lisbon, Portugal

方案二:基于单词的Jaccard相似度

通过拆分字符串为单词集合,计算交集与并集的比例(Jaccard相似度),同时叠加子串匹配的权重,更符合语义层面的相似判断:

// 计算两个字符串的Jaccard相似度
function calculateJaccard(string $str1, string $str2): float {
    $words1 = array_unique(explode(' ', strtolower($str1)));
    $words2 = array_unique(explode(' ', strtolower($str2)));
    $intersection = array_intersect($words1, $words2);
    $union = array_unique(array_merge($words1, $words2));
    return count($union) === 0 ? 0 : count($intersection) / count($union);
}

function findMostSimilar(string $query, array $candidates): string {
    $bestMatch = $candidates[0];
    $highestScore = 0;
    $queryLower = strtolower($query);

    foreach ($candidates as $candidate) {
        $score = calculateJaccard($query, $candidate);
        // 包含完整查询额外加分
        if (str_contains(strtolower($candidate), $queryLower)) {
            $score += 0.5;
        }
        if ($score > $highestScore) {
            $highestScore = $score;
            $bestMatch = $candidate;
        }
    }

    return $bestMatch;
}

这两种方案都能优先识别包含完整查询的字符串,解决你之前的匹配偏差问题。

内容的提问来源于stack exchange,提问作者user896541

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 08:55:25