У меня есть большая хэш-таблица (массив со строковыми индексами) и поиск функции, которая быстро выбирает из нее первый (в идеале, Nth) элемент. array_shift()
и reset()
слишком медленны для моих нужд.
UPDATE : я также не ищу референсное решение, функция должна принимать выражения как в 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
Используйте array_slice
для получения массива только n-го элемента и array_pop
чтобы, наконец, получить его:
$nthItem = array_pop(array_slice($arr, $n, 1));
Ваш тест может быть ошибочным, поскольку:
$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);
пустой лямбда = 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)
Я не думаю, что вы можете получить быстрее, чем reset()
/ end()
для первого / последнего элемента.
Что касается N-го элемента, я не могу придумать ничего лучше этого:
function (&$hashmap, $n) { $keys = array_keys($hashmap); return $hashmap[$keys[$n]]; }
Конечно, для производительности это может быть настроено на наличие кэшированного массива $keys
(если hashmap не меняется очень часто). В этом случае, возможно, даже извлечение элементов из 0-го элемента может быть быстрее, чем при reset()
Чтобы получить первое:
function array_first(array $array) { foreach ($array as $value) return $value; return false; }
И хотя я не тестировал это для скорости, вы можете попробовать использовать array_values()
для преобразования массива в числовой индексный массив.
Чтобы получить первый элемент, попробуйте сбросить указатель массива с помощью reset (array & $ array). Затем получите текущее значение с помощью current (). Чтобы получить элемент Nth, используйте end (), чтобы установить указатель на последний элемент. На этом этапе вы сможете получить N-й элемент с current ().