I've got a big hashtable (array with string indexes) and looking for a function that quickly picks the first (ideally, also Nth) element from it. array_shift()
and reset()
are too slow for my needs.
UPDATE: i'm also not looking for a reference-based solution, the function should accept expressions as in get_first(some_func_returning_array())
ANSWER array_slice method (kudos Gumbo) seems to be the winner. Complete benchmarking code
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);
Results:
dummy = 0.393
slice = 0.433
values = 0.824
foreach = 0.929
reset = 0.935
array_shift = 0.954
keys = 1.371
Use array_slice
to get an array of just the n-th item and array_pop
to finally get it:
$nthItem = array_pop(array_slice($arr, $n, 1));
Your benchmark may be flawed, since:
$fn = function ($a) {
return array_shift($a);
};
timeit('array_shift', $fn);
array_shift = 1.242 (5432)
and
timeit('array_shift', array_shift);
array_shift = 0.026 (4433)
but also
$fn = function ($a) { }
timeit('empty lambda', $fn);
empty lambda = 0.501 (0)
That being said, another possible solution:
$v = array_values($a);
return $v[ $index ];
Sample Code:
$t = microtime(1);
$v = array_values($a); // cached
while($loops--) {
$b = $v[$loops];
}
array_values = 0.002 (5432)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With