2014-03-19 63 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