选择哈希的第N个元素的最快方法

时间:2011-06-07 09:36:56

标签: php arrays

我有一个很大的哈希表(带有字符串索引的数组),并且正在寻找一个快速从中挑选第一个(理想情况下也是第N个)元素的函数。 array_shift()reset()对我的需求来说太慢了。

更新:我也不是在寻找基于参考的解决方案,该函数应该接受get_first(some_func_returning_array())

中的表达式

ANSWER array_slice方法(kudos Gumbo)似乎是胜利者。完整的基准代码

function bigary($n) {
    $a = array();
    $s = range('A', 'Z');
    do {
        shuffle($s);
        $a[substr(implode('', $s), rand(10, 20))] = $n;
    } while(--$n);
    return $a;
}

function timeit($name, $fn) {
    global $results;

    $loops = 1000;
    $size  = 5432;

    static $a;
    if(!$a) $a = bigary($size);

    $t = microtime(1);
    for($i = 0; $i < $loops; $i++)
        $b = $fn($a);
    $results[$name] = microtime(1) - $t;
}

timeit('dummy', function ($a) { 
    // benchmark php function call overhead
});

timeit('array_shift', function ($a) { 
    return array_shift($a); 
});

timeit('reset', function ($a) { 
    return reset($a); 
});

timeit('foreach', function ($a) { 
    foreach($a as $b) return $b;
});

timeit('keys', function ($a) { 
    $b = array_keys($a); 
    return $a[$b[0]];
});

timeit('values', function ($a) { 
    $b = array_values($a); 
    return $b[0];
});

timeit('slice', function ($a) { 
    $b = array_slice($a, 0, 1); 
    return reset($b);
});

asort($results);

foreach($results as $name => $time)
    printf("%20s = %.3f\n", $name, $time);

结果:

           dummy = 0.393
           slice = 0.433
          values = 0.824
         foreach = 0.929
           reset = 0.935
     array_shift = 0.954
            keys = 1.371

5 个答案:

答案 0 :(得分:7)

使用array_slice获取 n 项的数组和array_pop以最终得到它:

$nthItem = array_pop(array_slice($arr, $n, 1));

答案 1 :(得分:4)

您的基准可能存在缺陷,因为:

$fn = function ($a) { 
    return array_shift($a); 
};
timeit('array_shift', $fn);
  

array_shift = 1.242(5432)

timeit('array_shift', array_shift);
  

array_shift = 0.026(4433)

但也

$fn = function ($a) { } 
timeit('empty lambda', $fn);
  

空lambda = 0.501(0)

话虽如此,另一种可能的解决方案是:

$v = array_values($a);
return $v[ $index ];

示例代码:

$t = microtime(1);
$v = array_values($a); // cached
while($loops--) {
    $b = $v[$loops];
}
  

array_values = 0.002(5432)

答案 2 :(得分:2)

对于第一个/最后一个元素,我认为你不能比reset() / end()更快。

关于第N个元素,我想不出比这更好的东西:

function (&$hashmap, $n) {
    $keys = array_keys($hashmap);
    return $hashmap[$keys[$n]];
}

当然,对于性能,可以调整为具有预缓存的$keys数组(如果hashmap不经常更改)。在这种情况下,甚至第0个元素检索可能比使用reset()

更快

答案 3 :(得分:1)

获得第一个:

function array_first(array $array) {
     foreach ($array as $value) return $value;
     return false;
}

虽然我没有测试这个速度,但您可以尝试使用array_values()将数组转换为数字索引数组。

答案 4 :(得分:1)

要获取第一个元素,请尝试使用reset(array&amp; $ array)重置数组的指针。 然后用current()获取当前值。要获取第N个元素,请使用end(),将指针设置为最后一个项目。此时,您应该能够使用current()获取第N个项目。