2014-03-19 105 views
0

什麼是獲得兩個鍵之間數組的子陣列的最有效方式。PHP獲得兩個陣列鍵之間的子陣列

因此,例如,

$arr=array(); 
$arr['2014-03-01']='something'; 
$arr['2014-03-03']='something'; 
$arr['2014-02-04']='something'; 
$arr['2014-03-05']='something'; 
$arr['2014-03-07']='something'; 
$arr['2014-03-09']='something'; 
$arr['2014-01-04']='something'; 
$arr['2014-03-31']='something'; 

獲得兩個鍵間的子陣 即啓動鍵:2014年2月4日和結束鍵:2014年3月7日應該只返回一個數組:

$arr['2014-02-04']='something'; 
$arr['2014-03-05']='something'; 
$arr['2014-03-07']='something'; 

有沒有一種快速有效的方法來做到這一點沒有循環通過整個數組?

更新:我在這裏做了一個基準是結果:

$arr=array(); 
for ($i=1;$i<=1000000;$i++) { 
    $arr["$i"]=$i; 
} 

$time_start=microtime_float(); 

$start = '20000'; 
$end = '20010'; 

$offset = array_search($start, array_keys($arr)); 
$length = array_search($end, array_keys($arr)) - $offset + 1; 
$output = array_slice($arr, $offset, $length); 
print_r($output); 
$time_end = microtime_float(); 
$time = $time_end - $time_start; 
echo "TIME=$time\n"; 
echo "\n============\n"; 
$time_start=microtime_float(); 

$result = array(); 
$start = '20000'; 
$end = '20010'; 

foreach ($arr as $key => $value) { 
    if ($key >= $start && $key <= $end) 
    $result[$key] = $value; 
} 
print_r($output); 
$time_end = microtime_float(); 
$time = $time_end - $time_start; 
echo "TIME=$time\n"; 

exit; 

結果:

Array 
(
    [0] => 20000 
    [1] => 20001 
    [2] => 20002 
    [3] => 20003 
    [4] => 20004 
    [5] => 20005 
    [6] => 20006 
    [7] => 20007 
    [8] => 20008 
    [9] => 20009 
    [10] => 20010 
) 
TIME=1.8481030464172 

============ 
Array 
(
    [0] => 20000 
    [1] => 20001 
    [2] => 20002 
    [3] => 20003 
    [4] => 20004 
    [5] => 20005 
    [6] => 20006 
    [7] => 20007 
    [8] => 20008 
    [9] => 20009 
    [10] => 20010 
) 
TIME=1.700336933136 

因此,一個簡單的循環似乎稍快。如果我開始進一步向下排列,優點會增加。你也可以使用break;一旦達到後一點。

+0

array_filter 「在每個值迭代」,所以不者優先 –

+0

嗯,好了,除非按鍵的排序前進,你無法放棄'迭代每個值'的問題。 – Achrome

+0

鍵按上述排序。 –

回答

4

最有效的方法是使用循環。

$result = array(); 
$start = '2014-02-04'; 
$end = '2014-03-07'; 

foreach ($arr as $key => $value) { 
    // your date format is string comparable, otherwise use strtotime to convert to unix timestamp. 
    if ($key >= $start && $key <= $end) { 
    $result[$key] = $value; 
    } 
} 

或者低效率的方法是使用array_flip交換鍵和值,然後使用array_filter到所需的密鑰,然後使用array_intersect_key得到結果。

+0

使用巨大的數組。無論如何做到這一點沒有循環? –

+0

@射線如果沒有循環,您將無法使用任何陣列。 – deceze

+0

@xdazz只要按鍵可以比較和排序,只能使用。不一定是一般的解決方案。 – deceze

2

您可以ksortarray_slicearray_search嘗試:

$start = '2014-02-04'; 
$end = '2014-03-07'; 

ksort($arr); 
$offset = array_search($start, array_keys($arr)); 
$length = array_search($end, array_keys($arr)) - $offset + 1; 
$output = array_slice($arr, $offset, $length); 

var_dump($output); 

輸出:

array (size=5) 
    '2014-02-04' => string 'something' (length=9) 
    '2014-03-01' => string 'something' (length=9) 
    '2014-03-03' => string 'something' (length=9) 
    '2014-03-05' => string 'something' (length=9) 
    '2014-03-07' => string 'something' (length=9) 
+0

此解決方案假定數組已排序。 :) – Achrome

+0

@Achrome它是。看看'ksort'。 – hsz

+0

我知道ksort。我懷疑它比一個簡單的循環結構慢。 – Achrome