Intereting Posts
Как использовать сложные критерии внутри репозитория доктрины 2? Как справиться с этим HTML-кодом, эхом, с PHP, который как одинарные, так и двойные кавычки? Как получить имя сайта во время разработки плагина? Конвертация валюты для сайта электронной коммерции – Предотвращение неправильной полной корзины из-за округления htaccess Rewrite Rule Набор cookie не найден с php Как получить доступ к сессии клиента Magento извне Magento? PHP открыть другую веб-страницу с данными POST Session недоступен и не входит в число последних 1000 завершенных сеансов. Как это решить? Как получить __debugInfo для работы с XDebug? Как предотвратить дублирование вставок в таблицу Как расширить Joomla! к моему пользовательскому файлу PHP Поле MYSQL Date всегда выводит 0000-00-00 MySQL Query, group by, а затем упорядочивает по последнему слову с условием CakePHP: разбиение на страницы, сортировка, фильтрация данных из кэшированных таблиц

самый быстрый способ выбрать N-й элемент хэша

У меня есть большая хэш-таблица (массив со строковыми индексами) и поиск функции, которая быстро выбирает из нее первый (в идеале, 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 ().