2009-11-18 52 views
0

我在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 *」)

由於在提前進行任何輸入。

+0

有多快,現在和你多麼想加快步伐? – intgr 2009-11-21 20:07:22

回答

1

對於節省時間的訪問,我認爲最簡單的解決方案是對數組進行排序,並使用binary search algorithm的修改後的變體來查找與您的查詢匹配的較低和較高的數組邊界。這是有效的,因爲具有相似前綴的字符串總是按順序排序。

一旦你有這個範圍,獲取匹配元素是一個簡單的for循環。

顯然這不是一件小事,所以不要浪費任何時間,除非這個真的是是一個性能問題。不成熟的優化,你知道鑽...

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)

UPDATE:

你需要計算在字符串中有多少次 「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]; 
+0

這就是我現在正在做的。我擔心儘管調用get_values()一百次(有一百個循環)的性能很重。我可能不會去做某種預先分類。 – 2009-11-21 16:30:31

+0

Pekka,新建議的解決方案如何爲您工作? – 2009-11-26 07:50:27

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]; 
} 
+0

我可能不會解開它們。感謝您的意見。 – 2009-11-21 16:29:31

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); 
+0

當被多次調用時,這與我目前使用的函數有相同的缺點:它總是必須遍歷整個數組。 – 2009-11-21 16:31:32

+0

當然,它遍歷整個數組。你還將如何檢查數組中的每個項目? (因爲你排除了任何其他選項,比如「一種完全不同的存儲方式」(例如,緩存結果,使用數據庫等))這種方法很快,但我確實授予它它不是神奇的瞬間。 – GZipp 2009-11-26 14:26:44