在 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 中,在数组中搜索包含子字符串的值的快速方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 PHP 搜索包含多个单词的值的数据库?

如何在php中修剪数组值的空格

php 创建包含变量名和它们的值的数组函数

如何在 Jquery 中搜索数组,如 SQL LIKE %value% 语句

php compact() 函数

javascript - 在对象数组中,返回任何值与特定字符串匹配的对象