在 PHP 中,在数组中搜索包含子字符串的值的快速方法是啥?
Posted
技术标签:
【中文标题】在 PHP 中,在数组中搜索包含子字符串的值的快速方法是啥?【英文标题】:In PHP, what is a fast way to search an array for values which contain a substring?在 PHP 中,在数组中搜索包含子字符串的值的快速方法是什么? 【发布时间】:2011-01-07 15:42:23 【问题描述】:我有一组按字母顺序排列的街道名称,这些名称是从 Web 服务中收集的。该数组存在于服务器端。
在客户端,用户开始输入他居住的街道名称,AJAX 用于返回与部分街道名称最接近的匹配列表,以及数组中接下来的 9 个街道名称(列表在他打字时更新)。
例如,如果用户输入“al”,我希望结果如下所示:
奥尔巴尼高速公路 阿尔本斯谷 阿尔卡斯顿路 亚历克斯·伍德博士 爱丽丝路 阿拉瓦Ct 艾伦路 Alloway Pl 奥尔伍德大道 阿罗拉街 阿曼达博士这是我的尝试:
$matches = array();
for($i = 0; $i < count($streetNames); $i++)
if( (stripos($streetNames, $input) === 0 && count($matches) == 0) || count($matches) < 10 )
$matches[] = $streetNames[$i];
else
break;
还有其他人知道更快的方法吗?
请注意:我无法控制如何从数据库中获取此列表 - 它来自外部 Web 服务。
【问题讨论】:
好吧,要找出最快的方法,您必须对其进行基准测试才能确定。但如果这是来自外部网络服务,我会说建立与网络服务的连接将比您获得答案的任何代码慢。 是的,我已经通过将网络服务器返回的数据缓存 24 小时来解决这个问题。我们市镇的街道名称一般不会发生太大变化 - 但有很多开发正在进行,新街道不断涌现,所以 24 小时似乎是一个不错的时间。 【参考方案1】:无法确定它是否更快,但这是我的版本。
$input = 'al';
$matches = array_filter($streetNames, create_function('$v','return (stripos($v,'.$input.') !== false ? true : false);'));
$weight = array_map(create_function('$v','return array($v,levenshtein('.$input.',$v));'),$matches);
uasort($weight, create_function('$a,$b', 'if ($a[1] == $b[1]) return 0; return ($a[1] < $b[1]) ? -1 : 1;'));
$weight = array_slice($weight, 0, 10);
这会创建一个加权匹配列表。它们根据输入字符串和街道名称之间的距离进行排序。 0 代表真正的匹配。
生成的数组如下所示
array (
0 =>
array (
0 => 'Alola St',
1 => 7,
),
1 =>
array (
0 => 'Allen Rd',
1 => 7,
)
)
其中 0 => 街道名称和 1 => levenshtein 距离
【讨论】:
对我来说,如果没有这样的权重或任何你想称呼它的东西,自动完成是不完整的。但当然,这不是唯一的方法。只是概念的快速证明。【参考方案2】:我想你要找的是preg_grep()
您可以搜索以输入文本开头的元素:
$result = preg_grep('/^$input/', $streetNames);
或者对于在任何地方包含文本的元素:
$result = preg_grep('/$input/', $streetNames);
或者您也可以将搜索锚定到末尾,但这看起来没那么有用
【讨论】:
感谢您的回答,我实际上从未听说过 preg_grep。虽然我不会在这种情况下使用它,但它看起来真的很方便,我会把它归档以备后用:)【参考方案3】:比查看所有字符串更快的唯一方法是为这种事情优化数据结构,trie。您可能无法控制 Web 服务为您提供的内容,但如果您可以在服务器上缓存结果并重用它来处理许多请求,那么构建一个 trie 并使用它会快得多。
【讨论】:
有趣,因为我实际上正在缓存来自 Web 服务器的数据。我一定会调查的:) 伙计,传奇般的回应!也找到了一个很好的 php 资源:phpir.com/tries-and-wildcards【参考方案4】:使用preg_grep()
:
$matches = preg_grep('/al/', $streetNames);
注意:像您这样的方法将是蛮力搜索。如果您正在搜索大量名称(数十万)或搜索大量次,那么您可能需要更好的东西。但是,对于小型数据集,这很好。
【讨论】:
谢谢克莱图斯。虽然我不会在这个特定的例子中使用这个方法,但你让我看到了一个我一直忽略的功能。我肯定会在某个地方使用它。再次感谢:) 这绝不是一个快速的方法:|以上是关于在 PHP 中,在数组中搜索包含子字符串的值的快速方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章