提问人:Pekka 提问时间:11/18/2009 更新时间:11/24/2009 访问量:194
提取数组部分的快速方法?
Fast way to extract portions of array?
问:
我在PHP中有一个很大的数组。
它包含使用下划线拆分为一种类别的字符串:
category1_property
category1_category2_category3
category2_category3_category4_category5
我有一个名为
array get_values($prefix)
返回以给定前缀开头的数组的所有值,例如
get_values("category2_category3_");
这个函数 foreach()es 每次都会遍历整个数组,收集所有以前缀开头的字符串,即一个简单的
foreach ($my_array as $line)
if (substr($line, 0, strlen($prefix)) == $prefix))
array_push ($result, $line);
在性能方面,我感觉很糟糕,尤其是看到每个请求执行数十次此操作。
有没有人知道一种方法可以加快速度,而不必诉诸完全不同的数据存储方式?
使用数据库可能既快速又聪明,但我想避免这种情况。数据来自文件,我无法将其移植到数据库。
将构造预先排序或拆分为多维数组或对象不是一种选择,因为我有时需要查询类别名称的各个部分(例如“category1_ca*”)
提前感谢您的任何意见。
答:
为了节省时间进行访问,我认为最简单的解决方案是对数组进行排序,并使用二进制搜索算法的修改变体来查找与您的查询匹配的下限和上限数组边界。这之所以有效,是因为具有相似前缀的字符串始终按顺序排序。
一旦你有了这个范围,获取匹配的元素就是一个简单的for循环。
显然,这不是一项微不足道的任务,所以不要浪费任何时间,除非这真的是一个性能问题。过早优化,你懂钻...
我不清楚get_values功能应该匹配什么 - 无论如何,这可能是您正在寻找的性能友好型解决方案?
function get_values($prefix) {
$included_array_from_file = array ( "category1_property", "category1_category2_category3", "category2_category3_category4_category5");
foreach($included_array_from_file as $val) {
if(strpos($val,$prefix)===0) {
$out[] = $val;
}
}
return $out;
}
print_r( get_values("category2_category3_") );
输出:
Array ( [0] => category2_category3_category4_category5 )
更新:
你需要计算字符串中“category2_category3_”出现多少次,对吧?在这种情况下,我建议您为完整字符串创建一个多维数组,并计算每次出现次数,如以下示例所示: (请注意,该示例仅说明了如何完成 - 该示例目前失败,因为我不确定如何动态构建多维数组,您可能需要在向数组添加项目时调用另一个“创建数组”函数。
失败(“无法将标量值用作数组”) - 不确定如何操作。
$data = array("category1_property", "category1_category2_category3", "category2_category3_category4_category5");
$counter = array();
foreach($data as $val) {
foreach(explode(":",$val) as $val2) {
// Now, create a multi-dimensional array with the category items as keys and increment the value by one for each item in the string, as in this example:
// "category2_category3_category4_category5" ... turns into:
// $counter[category2] += 1;
// $counter[category2][category3] += 1;
// $counter[category2][category3][category4] += 1;
// $counter[category2][category3][category4][category5] += 1;
}
}
预期用途:
echo $counter[category2][category3];
评论
我想你正在寻找preg_grep
你真的限制了选择!即便如此,我认为预先拆分数据可能是要走的路。考虑:
前缀 , , 变为'cat1_cat2_cat3_dog'='fido'
'cat1_cat2_cat3_fish'='goldie'
'cat1_cat2_cat3_frog'='kermit
$arr[cat1][cat2][cat3][dog]=fido
$arr[cat1][cat2][cat3][fish]=goldie
$arr[cat1][cat2][cat3][frog]=kermit
如果您想要所有带有前缀的内容:cat1_cat2
$arr['cat1']['cat2']=array('cat3'=>array('dog'=>'fido','fish'=>'goldie'));
如果您想要所有带有前缀的内容,则只需搜索以下术语:cat1_cat2_cat3_f*
$arr['cat1']['cat2']['cat3']
$matches=preg_grep("/^f/",array_keys($arr['cat1']['cat2']['cat3']));
foreach($matches as $k){
$results[]=$arr['cat1']['cat2]['cat3'][$k];
}
评论
或者你可以在 array_filter() 中使用匿名函数:
function get_values($arr, $str)
{
$func = create_function('$item', 'return (strpos($item, "' . $str . '") === 0);');
return array_filter($arr, $func);
}
$prefix = 'category1';
$result = get_values($my_array, $prefix);
评论
上一个:对平面列表进行排序,按父级分组
下一个:重置页面某个区域的 CSS?
评论