缓存键查找 - 查找“最近”或相同的键

时间:2011-11-11 02:15:15

标签: php caching string-matching

编辑:我以一种与实现无关的方式来处理这个问题,但这是我所追求的细节。

我有一组函数,它们对数组执行读写操作,允许使用以下语法:

$map->{'foo.bar.baz'}; // same as $array['foo']['bar']['baz'];

即使在敏感的错误报告环境中,在没有目标数组元素的情况下也不会发出通知,而是返回null。无论如何,为了提高访问性能,我已经为读取方法添加了缓存功能。

每当执行写入操作时,缓存都会失效(并清除),但重复读取(此时到同一元素)会显着提高性能。缓存的“值”是对数组元素的引用,而不是元素值的副本。

函数通过迭代分解字符串(数组元素路径)来工作,例如foo.bar.baz查找(,如果它存在){{ 1}}。

现在,缓存只是一个路径关联数组( keys ),引用给定数组的相应元素,例如:

$array['foo']['bar']['baz']

但是,我想我可以通过查找对给定路径的最近父级的引用而不是特定的路径来进一步提高缓存性能。例如:

'foo' => &$array['foo'],
'foo.bar' => &$array['foo']['bar'],

由于// given $map->{'foo.bar'}; // read operation // followed by $map->{'foo.bar.baz.zip'}; // another read operation 的缓存中不存在密钥,因此必须对数组执行全新的提取。我希望我可以利用存储的对foo.bar.baz.zip的引用,然后只针对它执行foo.bar的提取。

所有这些加起来找到最接近的字符串匹配,并包括正在读取的当前路径。

levenshtein()似乎是一种合适的可能性(由@mfonda描述 - 谢谢你的方式)如果包装了一些初步检查以避免不必要的迭代,但我注意到了由于它区分两个字符串的方式,它有时会返回无效匹配,在baz.zip上找到foo.zoo foo.bar.zoo


快一点;我正在寻找匹配字符串的最快方法,从字符串数组( keys )中找到最接近的(或相同的),我的意思是:< / p>

foo.bar

字符串“closeness”由匹配的最长字符串(不长于检查字符串)确定。因此// given $string = 'foo.bar.baz'; // and $list_1 = array( 'foo' => null 'foo.bar.baz.zip' => null, ); // and $list_2 = array( 'foo' => null, 'foo.bar' => null, 'foo.goo.baz' => null, ); // and $list_3 = array( 'foo.bar.baz' => null, 'foo.bar.baz.zip' => null, ); // yields echo magic_match($string, $list_1); // foo echo magic_match($string, $list_2); // foo.bar echo magic_match($string, $list_3); // foo.bar.baz abca匹配abcd进行了对帐,因为a超出了支票的长度。

我现在正在做一些测试,但我确信SO社区中的PHP开发人员已经设计了一些东西。

看来(遗憾的是)PHP中没有本机函数来执行此操作;在strstr()之间,preg_grep()不能完成任务)和奇怪的替代组合,似乎没有什么特别快。


此时,要确定abcd是否确切存在(或不),我们可以从以下开始:

$string

由于字符串是用if(!isset($list[$string])){ // proceed with processing to find closest }else{ // identical found } 分隔的,我们可以.字符串并逐步内爆:

explode()

然而,通过迭代持续重新插入字符串可能会很昂贵。

2 个答案:

答案 0 :(得分:1)

您可能需要查看similar_text()levenshtein()。这些函数可以衡量两个字符串的相似程度。基于此,您可以选择最接近的匹配。

答案 1 :(得分:0)

你的匹配标准有点模糊。所以你可能不得不自己做。我看到有不同的情况,取决于长度。那怎么样:

function magic_match($str, $list) {
   $scores = array();
   foreach($list as $item) {

      if (strlen($str) > strlen($item) {
         // one type of compare
         $scores[] = array($item, $score);
      }
      else {
         // other type
         $scores[] = array($item, $score);
      }
   }

   // return item with highest score
}