在PHP中查找顶部相似的字符串?

3
我可以帮您进行翻译。以下是需要翻译的内容:

我有一个包含17,000个字符串的数组。其中许多字符串具有相似的匹配项,例如:

User Report XYZ123
Bob Smith
User Report YEI723
User Report
User Report
Number of Hits 27
Frank's Weekly Transaction Report
Transaction Report 123
什么是查找顶部“相似字符串”的最佳方法?例如,使用上面的示例,我希望看到“用户报告”和“交易报告”作为顶部“相似字符串”中的两个。

“最相似”的应该是“Frank的每周交易报告”和“交易报告123”,而不是其他的。 - MightyPork
1
一种简单的方法是使用levenshtein()函数来确定两个字符串之间的距离。 - Nadh
4个回答

0
你可以计算每个字符串与其他字符串的Levenstein距离,然后按照该值对它们进行排序。
$strings = array('str1', 'str2', 'car', 'dog', 'apple', 'house', 'str3');
$len = count($strings);

$distances = array_fill(0, $len, 0);

for($i=0; $i<$len-1; ++$i)
    for($j=$i+1; $j<$len; ++$j)
    {
        $dist = levenshtein($strings[$i], $strings[$j]);
        $distances[$i] += $dist;
        $distances[$j] += $dist;
    }

// Here $distances indicates how of "similar" is each string
// The lower values are more "similar"

0

不需要提供所有源代码来完成这个任务,你可以遍历数组并删除你认为无用的组件,例如任何带有数字的字母等。

然后,您可以使用array_count_values()函数并对该数组进行排序以查看涉及最多的前几个。


0
我想你可以通过foreach循环遍历每个字符串,并消除那些在特定搜索中不需要的字符串。然后,通过另一个foreach循环遍历剩下的字符串,并逐渐缩小你感兴趣的字符串数量,直到只剩下几个。然后按字母顺序对它们进行排序。

-1
如果您能够将所有字符串作为数组获取并在foreach()中循环,就像这样:
$string_array = array('string', 'string1', 'string2', 'does-not-match');
$needle = 'string';

$results = array();
foreach($string_array as $key => $val):
    if (fnmatch($needle, $val):
        $results[] = $val;
    endif;
endforeach;

最终,您应该得到与$needle匹配的条目。作为fnmatch()的替代方案,您可以使用preg_match(),并将模式设置为/string/i
$string_array = array('string', 'string1', 'string2', 'does-not-match');
$needle = '/string/i';

$results = array();
foreach($string_array as $key => $val):
    if (!empty(preg_match($needle, $val)):
        $results[] = $val;
    endif;
endforeach;

请注意,使用empty()和传递preg_match()的结果可能会出现问题。

在PHP 5.5之前,empty()仅支持变量;其他任何内容都将导致解析错误。换句话说,以下内容将无法正常工作:empty(trim($name))。而应该使用trim($name) == false。

在PHP版本5.3.x < 5.4中不应发出错误。


为什么要用 fnmatch?那太糟糕了。还不如用 md5 :s - Halcyon
1
fnmatch()函数检查传递的字符串是否与给定的shell通配符模式匹配。这使得fnmatch()等同于preg_match()函数。 - DaGhostman Dimitrov
2
输入是纯文本,没有正则表达式。如果其中一个输入字符串是 ".*",它看起来根本不像 "string" - Halcyon
在每个应用程序和每种情况下,用户输入都应该适当地进行消毒处理。例如,使用上面的例子,我希望看到“用户报告”和“交易报告”作为前两个“相似字符串”。OP 告诉了他想要什么,如果 $needle 是 "用户报告",那么结果应该包含示例数据中的 4 个条目。这使得你的评论不必要且不相关。 - DaGhostman Dimitrov
如何使用正则表达式从“用户报告”转到“交易报告”?我的意思是,你的答案毫无意义,而且你的解决方案也不是 OP 想要的。他想要将输入字符串与它们自身进行匹配。因此基本上是一个O平方算法。 - Halcyon
嗯,你可能有一点道理。我不得不读几遍这个问题,然后我意识到用户想要获取所有字符串之间的相似度。这使得我的答案无关紧要。感谢指正。 :) - DaGhostman Dimitrov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接