虽然@yceruto 的回答正确且内容丰富,但我想扩展更多见解并展示更现代的实现语法。
首先关于各个函数生成的分数...
-
levenshtein() 和 similar_text() 区分大小写,因此与 h 相比,大写的 H 与数字 6 一样不匹配。
-
levenshtein() 和 similar_text() 不支持多字节,因此像 ê 这样的重音字符不仅会被视为与 e 不匹配,而且可能会因为每个单独的字节不匹配而受到更重的惩罚。
如果要进行不区分大小写的比较,只需在执行前将两个字符串都转换为大写/小写即可。
如果您的应用程序需要多字节支持,您应该搜索提供此功能的现有存储库。
对于那些愿意进行更深入研究的人来说,其他技术包括 metaphone() 和 soundex(),但我不会在这个答案中深入研究这些主题。
分数:
Test vs "hello" | levenshtein | similar_text | similar_text's percent |
----------------+----------------+----------------+----------------------------|
H3||0 | 5 | 0 | 0 |
Hallo | 2 | 3 | 60 |
aloha | 5 | 2 | 40 |
h | 4 | 1 | 33.333333333333 |
hallo | 1 | 4 | 80 |
hallå | 3 | 3 | 54.545454545455 |
hel | 2 | 3 | 75 |
helicopter | 6 | 4 | 53.333333333333 |
hellacious | 5 | 5 | 66.666666666667 |
hello | 0 | 5 | 100 |
hello y'all | 6 | 5 | 62.5 |
hello yall | 5 | 5 | 66.666666666667 |
helów | 3 | 3 | 54.545454545455 |
hey hello | 4 | 5 | 71.428571428571 |
hola | 3 | 2 | 44.444444444444 |
hêllo | 2 | 4 | 72.727272727273 |
mellow yellow | 9 | 4 | 44.444444444444 |
try | 5 | 0 | 0 |
按levenshtein() PHP7+ (Demo)排序
usort($testStrings, function($a, $b) use ($needle) {
return levenshtein($needle, $a) <=> levenshtein($needle, $b);
});
按levenshtein() PHP7.4+ (Demo)排序
usort($testStrings, fn($a, $b) => levenshtein($needle, $a) <=> levenshtein($needle, $b));
**请注意,$a 和 $b 已更改 DESC 排序的 <=> 评估的两侧。
请注意,hello 不能保证被定位为第一个元素
按similar_text() PHP7+ (Demo) 排序
usort($testStrings, function($a, $b) use ($needle) {
return similar_text($needle, $b) <=> similar_text($needle, $a);
});
按similar_text() PHP7.4+ (Demo)排序
usort($testStrings, fn($a, $b) => similar_text($needle, $b) <=> similar_text($needle, $a));
注意hallå 和helicopter 通过similar_text() 的返回值与similar_text() 的百分比值的差异。
按similar_text() 的 PHP7+ 百分比排序 (Demo)
usort($testStrings, function($a, $b) use ($needle) {
similar_text($needle, $a, $percentA);
similar_text($needle, $b, $percentB);
return $percentB <=> $percentA;
});
按similar_text() 的百分比 PHP7.4+ (Demo) 排序
usort($testStrings, fn($a, $b) =>
[is_int(similar_text($needle, $b, $percentB)), $percentB]
<=>
[is_int(similar_text($needle, $a, $percentA)), $percentA]
);
请注意,我通过将similar_text() 的返回值转换为true,然后使用生成的percent 值来消除不需要的返回值——这允许生成百分比值而不返回很快,因为箭头函数语法不允许多行执行。
按levenshtein() 高效排序,然后只在需要抢七时调用similar_text(),PHP7+ (Demo)
usort($testStrings, function($a, $b) use ($needle) {
return levenshtein($needle, $a) <=> levenshtein($needle, $b)
?: similar_text($needle, $b) <=> similar_text($needle, $a);
});
按levenshtein() 高效排序,然后仅调用similar_text() 并在需要抢七时使用其百分比,PHP7.4+ (Demo)
usort($testStrings, fn($a, $b) =>
levenshtein($needle, $a) <=> levenshtein($needle, $b)
?: similar_text($needle, $b) <=> similar_text($needle, $a)
);
就我个人而言,除了levenshtein(),我从不在我的项目中使用任何其他东西,因为它始终如一地提供我正在寻找的结果。