提取数组部分的快速方法?

时间:2009-11-18 14:18:50

标签: php arrays sorting

我在PHP中有一个大型数组。

它包含使用下划线分割为一种类别的字符串:

category1_property
category1_category2_category3
category2_category3_category4_category5

我有一个名为

的函数
array get_values($prefix) 

返回以给定前缀开头的数组的所有值,例如

get_values("category2_category3_");

这个函数foreach()每次遍历整个数组,收集所有以前缀开头的字符串,即一个简单的

foreach ($my_array as $line)
 if (substr($line, 0, strlen($prefix)) == $prefix)) 
  array_push ($result, $line);

我在表现方面做得很糟糕,特别是看到每个请求执行此操作数十次。

有没有人知道如何加快速度,而不必采用完全不同的方式存储数据?

使用数据库可能既快又聪明,但我想避免这种情况。数据来自文件,我无法将其移植到数据库。

将构造预先排序或拆分为多维数组或对象不是一种选择,因为我有时需要查询类别名称的部分(例如“category1_ca *”)

提前感谢任何输入。

5 个答案:

答案 0 :(得分:1)

对于节省时间的访问,我认为最简单的解决方案是对数组进行排序,并使用binary search algorithm的修改变体来查找与查询匹配的较低和较高数组边界。这是有效的,因为具有相似前缀的字符串总是按顺序排序。

获得此范围后,获取匹配元素是一个简单的for循环。

显然这不是一项微不足道的任务,所以不要浪费任何时间在此,除非真的是性能问题。过早优化,你知道钻...

答案 1 :(得分:1)

我不清楚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_”的次数,对吗?在这种情况下,我建议您为完整字符串创建一个多维数组,并按照此示例中所示计算每个匹配项:(请注意,该示例仅说明了如何完成 - 示例当前失败,因为我不知道如何动态构建多维数组,在向数组添加项目时可能需要调用另一个“create array”函数。)

失败(“不能将标量值用作数组”) - 不确定如何使用。

$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];

答案 2 :(得分:1)

我认为你正在寻找preg_grep

答案 3 :(得分:1)

你真的限制了选项!即便如此,我认为预先分割数据可能是最佳选择。考虑:

前缀'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];
}

答案 4 :(得分:0)

或者你可以使用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);