В порядке,
Я знаю все о array_pop()
, но удаляет последний элемент. Каков наилучший способ получить последний элемент массива без его удаления?
EDIT: Вот бонус:
$array = array('a' => 'a', 'b' => 'b', 'c' => 'c');
или даже
$array = array('a', 'b', 'c', 'd'); unset($array[2]); echo $array[sizeof($array) - 1]; // Output: PHP Notice: Undefined offset: 2 in - on line 4
с$array = array('a', 'b', 'c', 'd'); unset($array[2]); echo $array[sizeof($array) - 1]; // Output: PHP Notice: Undefined offset: 2 in - on line 4
Короткие и сладкие.
Я придумал решение для удаления сообщения об ошибке и сохранения однострочной формы и эффективной производительности:
$lastEl = array_values(array_slice($array, -1))[0];
– предыдущее решение
$lastEl = array_pop((array_slice($array, -1)));
Примечание. Дополнительные скобки необходимы, чтобы избежать PHP Strict standards: Only variables should be passed by reference
.
Пытаться
$myLastElement = end($yourArray);
Чтобы сбросить его (спасибо @hopeseekr):
reset($yourArray);
Ссылка на руководство
@David Murdoch добавил: $myLastElement = end(array_values($yourArray));// and now you don't need to call reset().
В E_STRICT это вызывает предупреждение
Strict Standards: Only variables should be passed by reference
Спасибо o_O Tync и всем!
Что случилось с array_slice($array, -1)
? (См. Руководство: http://us1.php.net/array_slice )
array_slice()
возвращает массив. Наверное, не то, что вы ищете. Вы хотите элемент.
Многие ответы в этой теме представляют нам множество различных вариантов. Чтобы иметь возможность выбирать из них, мне нужно было понять их поведение и производительность. В этом ответе я поделюсь с вами своими выводами, сравнивая с версиями PHP 5.6.29
и 5.6.29
. Параметры, которые я буду тестировать:
$x = array_values(array_slice($array, -1))[0];
$x = array_slice($array, -1)[0];
$x = array_pop((array_slice($array, -1)));
$x = array_pop((array_slice($array, -1, 1)));
$x = end($array); reset($array);
$x = end($array); reset($array);
$x = end((array_values($array)));
$x = $array[count($array)-1];
$keys = array_keys($array); $x = $array[$keys[count($keys)-1]];
$keys = array_keys($array); $x = $array[$keys[count($keys)-1]];
$x = $array[] = array_pop($array);
Тестовые входы:
$array = null;
$array = [];
$array = ["a","b","c",null];
$array = ["a","b","c","d"];
$array = []; $array[1] = "a"; $array[2] = "b"; $array[0] = "c";
$array = []; $array[1] = "a"; $array[2] = "b"; $array[0] = "c";
$array = []; for($i=0;$i<100;$i++) { $array[] = $i; }
$array = []; for($i=0;$i<100;$i++) { $array[] = $i; }
$array = []; for($i=0;$i<100000;$i++) { $array[] = $i; }
$array = []; for($i=0;$i<100000;$i++) { $array[] = $i; }
Для тестирования я буду использовать 5.6.29
и 5.6.29
например:
sudo docker run -it --rm php:5.6.29-cli php -r '<<<CODE HERE>>>'
Каждая комбинация из вышеперечисленного <<option code>>
s, приведенный выше тест <<input code>>
s будет запущен в обеих версиях PHP. Для каждого тестового запуска используется следующий фрагмент кода:
<<input code>> error_reporting(E_ALL); <<option code>> error_reporting(0); $before=microtime(TRUE); for($i=0;$i<100;$i++){echo ".";for($j=0;$j<1;$j++){ <<option code>> }}; $after=microtime(TRUE); echo "\n"; var_dump($x); echo round(($after-$before)*10);
Для каждого запуска это будет var_dump последнее полученное последнее значение тестового ввода и печать средней продолжительности одной итерации в наносекундах .
Результаты приведены ниже:
/=======================================================================================================================================================================================================================================================================================================\ || || TESTINPUT - 5 . 6 . 2 9 || TESTINPUT - 7 . 1 . 0 || || || null | empty | last_null | auto_idx | shuffle | 100 | 100000 || null | empty | last_null | auto_idx | shuffle | 100 | 100000 || ||===========================OPTIONS - ERRORS==========================++===============+===============+===============+===============+===============+===============+===============++===============+===============+===============+===============+===============+===============+===============<| || 1. $x = array_values(array_slice($array, -1))[0]; || W1 + W2 | N1 | - | - | - | - | - || W1 + W2 | N1 | - | - | - | - | - || || 2. $x = array_slice($array, -1)[0]; || W1 | N1 | - | - | - | - | - || W1 | N1 | - | - | - | - | - || || 3. $x = array_pop((array_slice($array, -1))); || W1 + W3 | - | - | - | - | - | - || W1 + N2 + W3 | N2 | N2 | N2 | N2 | N2 | N2 || || 4. $x = array_pop((array_slice($array, -1, 1))); || W1 + W3 | - | - | - | - | - | - || W1 + N2 + W3 | N2 | N2 | N2 | N2 | N2 | N2 || || 5. $x = end($array); reset($array); || W4 + W5 | - | - | - | - | - | - || W4 + W5 | - | - | - | - | - | - || || 6. $x = end((array_values($array))); || W2 + W4 | - | - | - | - | - | - || W2 + N2 + W4 | N2 | N2 | N2 | N2 | N2 | N2 || || 7. $x = $array[count($array)-1]; || - | N3 | - | - | - | - | - || - | N3 | - | - | - | - | - || || 8. $keys = array_keys($array); $x = $array[$keys[count($keys)-1]]; || W5 | N3 + N4 | - | - | - | - | - || W5 | N3 + N4 | - | - | - | - | - || || 9. $x = $array[] = array_pop($array); || W3 | - | - | - | - | - | - || W3 | - | - | - | - | - | - || ||=======================OPTIONS - VALUE RETRIEVED=====================++===============+===============+===============+===============+===============+===============+===============++===============+===============+===============+===============+===============+===============+===============<| || 1. $x = array_values(array_slice($array, -1))[0]; || NULL | NULL | NULL | string(1) "d" | string(1) "c" | int(99) | int(9999999) || NULL | NULL | NULL | string(1) "d" | string(1) "c" | int(99) | int(9999999) || || 2. $x = array_slice($array, -1)[0]; || NULL | NULL | NULL | string(1) "d" | string(1) "c" | int(99) | int(9999999) || NULL | NULL | NULL | string(1) "d" | string(1) "c" | int(99) | int(9999999) || || 3. $x = array_pop((array_slice($array, -1))); || NULL | NULL | NULL | string(1) "d" | string(1) "c" | int(99) | int(9999999) || NULL | NULL | NULL | string(1) "d" | string(1) "c" | int(99) | int(9999999) || || 4. $x = array_pop((array_slice($array, -1, 1))); || NULL | NULL | NULL | string(1) "d" | string(1) "c" | int(99) | int(9999999) || NULL | NULL | NULL | string(1) "d" | string(1) "c" | int(99) | int(9999999) || || 5. $x = end($array); reset($array); || NULL | bool(false) | NULL | string(1) "d" | string(1) "c" | int(99) | int(9999999) || NULL | bool(false) | NULL | string(1) "d" | string(1) "c" | int(99) | int(9999999) || || 6. $x = end((array_values($array))); || NULL | bool(false) | NULL | string(1) "d" | string(1) "c" | int(99) | int(9999999) || NULL | bool(false) | NULL | string(1) "d" | string(1) "c" | int(99) | int(9999999) || || 7. $x = $array[count($array)-1]; || NULL | NULL | NULL | string(1) "d" | string(1) "b" | int(99) | int(9999999) || NULL | NULL | NULL | string(1) "d" | string(1) "b" | int(99) | int(9999999) || || 8. $keys = array_keys($array); $x = $array[$keys[count($keys)-1]]; || NULL | NULL | NULL | string(1) "d" | string(1) "c" | int(99) | int(9999999) || NULL | NULL | NULL | string(1) "d" | string(1) "c" | int(99) | int(9999999) || || 9. $x = $array[] = array_pop($array); || NULL | NULL | NULL | string(1) "d" | string(1) "c" | int(99) | int(9999999) || NULL | NULL | NULL | string(1) "d" | string(1) "c" | int(99) | int(9999999) || ||================OPTIONS - NANOSECONDS PER ITERATION==================++===============+===============+===============+===============+===============+===============+===============++===============+===============+===============+===============+===============+===============+===============<| || 1. $x = array_values(array_slice($array, -1))[0]; || 681 | 413 | 320 | 321 | 317 | 649 | 1.034.200 || 642 | 231 | 102 | 110 | 105 | 174 | 86.700 || || 2. $x = array_slice($array, -1)[0]; || 362 | 301 | 206 | 205 | 202 | 530 | 1.006.000 || 329 | 205 | 63 | 67 | 65 | 134 | 87.000 || || 3. $x = array_pop((array_slice($array, -1))); || 671 | 183 | 273 | 273 | 269 | 597 | 997.200 || 807 | 244 | 282 | 305 | 285 | 355 | 87.300 || || 4. $x = array_pop((array_slice($array, -1, 1))); || 687 | 206 | 303 | 305 | 294 | 625 | 1.003.600 || 812 | 249 | 284 | 288 | 287 | 359 | 87.200 || || 5. $x = end($array); reset($array); || 671 | 136 | 137 | 140 | 137 | 137 | 139 || 632 | 43 | 45 | 46 | 45 | 45 | 45 || || 6. $x = end((array_values($array))); || 674 | 156 | 278 | 278 | 257 | 2.934 | 8.464.000 || 835 | 239 | 270 | 274 | 265 | 474 | 815.000 || || 7. $x = $array[count($array)-1]; || 90 | 257 | 102 | 101 | 101 | 106 | 102 || 31 | 190 | 32 | 34 | 35 | 32 | 32 || || 8. $keys = array_keys($array); $x = $array[$keys[count($keys)-1]]; || 420 | 543 | 365 | 369 | 334 | 3.498 | 12.190.000 || 358 | 373 | 90 | 97 | 89 | 333 | 1.322.000 || || 9. $x = $array[] = array_pop($array); || 145 | 150 | 144 | 144 | 143 | 144 | 143 || 46 | 46 | 46 | 49 | 48 | 46 | 47 || \=======================================================================================================================================================================================================================================================================================================/
Вышеупомянутые коды W arning и N otice переводятся как:
W1 = Warning: array_slice() expects parameter 1 to be array, null given in Command line code on line 1 W2 = Warning: array_values() expects parameter 1 to be array, null given in Command line code on line 1 W3 = Warning: array_pop() expects parameter 1 to be array, null given in Command line code on line 1 W4 = Warning: end() expects parameter 1 to be array, null given in Command line code on line 1 W5 = Warning: reset() expects parameter 1 to be array, null given in Command line code on line 1 W6 = Warning: array_keys() expects parameter 1 to be array, null given in Command line code on line 1 N1 = Notice: Undefined offset: 0 in Command line code on line 1 N2 = Notice: Only variables should be passed by reference in Command line code on line 1 N3 = Notice: Undefined offset: -1 in Command line code on line 1 N4 = Notice: Undefined index: in Command line code on line 1
Исходя из этого вывода, я делаю следующие выводы:
$x = end($array); reset($array);
$x = end($array); reset($array);
$x = $array[count($array)-1];
$x = $array[] = array_pop($array);
Лично мне не нравится по отношению к себе с внутренними указателями массива и предпочитаю решение в одном выражении. Поэтому рассказ, который я бы сам использовал:
$x = $array[count($array)-1];
$x = $array[] = array_pop($array);
$x = $array[] = array_pop($array);
Немного в зависимости от того, используете ли вы массив в виде стека или в очереди, вы можете делать варианты на опции 9.
Один из способов избежать ошибок при пересылке (например, «end (array_values ($ foo))») – использовать call_user_func или call_user_func_array:
// PHP Fatal error: Only variables can be passed by reference // No output (500 server error) var_dump(end(array(1, 2, 3))); // No errors, but modifies the array's internal pointer // Outputs "int(3)" var_dump(call_user_func('end', array(1, 2, 3))); // PHP Strict standards: Only variables should be passed by reference // Outputs "int(3)" var_dump(end(array_values(array(1, 2, 3)))); // No errors, doesn't change the array // Outputs "int(3)" var_dump(call_user_func('end', array_values(array(1, 2, 3))));
непроверенный: не будет ли это работать?
<?php $last_element=end(array_values($array)); ?>
Поскольку массив, возвращаемый array_values, мимолетен, никто не заботится о том, сброшен ли указатель.
и если вам нужен ключ, чтобы пойти с ним, я думаю, вы бы сделали:
<?php $last_key=end(array_keys($array)); ?>
Мне нужно это довольно часто, чтобы иметь дело со стеками, и я всегда сбиваюсь с толку, что нет встроенной функции, которая делает это без манипуляции с массивом или его внутренним указателем в той или иной форме.
Поэтому я обычно ношу вокруг функции утилиты, которая также безопасна для использования на ассоциативных массивах.
function array_last($array) { if (count($array) < 1) return null; $keys = array_keys($array); return $array[$keys[sizeof($keys) - 1]]; }
end () предоставит последний элемент массива
$array = array('a' => 'a', 'b' => 'b', 'c' => 'c'); echo end($array); //output: c $array1 = array('a', 'b', 'c', 'd'); echo end($array1); //output: d
Чтобы получить последний элемент массива, используйте:
$lastElement = array_slice($array, -1)[0];
эталонный тест
Я повторил 1000 раз, захватив последний элемент малых и больших массивов, который содержал 100 и 50 000 элементов, соответственно.
Method: $array[count($array)-1]; Small array (μs): 0.000319957733154 Large array (μs): 0.000526905059814 Note: Fastest! count() must access an internal length property. Note: This method only works if the array is naturally-keyed (0, 1, 2, ...). Method: array_slice($array, -1)[0]; Small array (μs): 0.00145292282104 Large array (μs): 0.499367952347 Method: array_pop((array_slice($array, -1, 1))); Small array (μs): 0.00162816047668 Large array (μs): 0.513121843338 Method: end($array); Small array (μs): 0.0028350353241 Large array (μs): 4.81077480316 Note: Slowest...
Я использовал PHP Version 5.5.32.
Для меня:
$last = $array[count($array) - 1];
С ассоциациями:
$last =array_values($array)[count($array - 1)]
Чтобы сделать это и избежать E_STRICT, и не возиться с внутренним указателем массива, вы можете использовать:
function lelement($array) {return end($array);} $last_element = lelement($array);
lelement работает только с копией, поэтому он не влияет на указатель массива.
Другое решение:
$array = array('a' => 'a', 'b' => 'b', 'c' => 'c'); $lastItem = $array[(array_keys($array)[(count($array)-1)])]; echo $lastItem;
$lastValue = end(array_values($array))
Никаких изменений в указателях $ array не производится. Это позволяет избежать
reset($array)
что может быть нежелательным в определенных условиях.
Для получения последнего значения из массива:
array_slice($arr,-1,1) ;
Для удаления последнего массива формы значений:
array_slice($arr,0,count($arr)-1) ;
Просто: $last_element = end((array_values($array)))
Не сбрасывает массив и не дает предупреждений STRICT.
PS. Поскольку у самого голосованного ответа все еще нет двойной круглой скобки, я представил этот ответ.
Еще одно возможное решение …
$last_element = array_reverse( $array )[0];
Как насчет:
current(array_slice($array, -1))
$array == []
(возвращает false
) Я думаю, что это небольшое улучшение по всем существующим ответам:
$lastElement = count($array) > 0 ? array_values(array_slice($array, -1))[0] : null;
end()
или решения, используя array_keys()
, особенно с большими массивами Если вам не нужно изменять внутренний указатель (поддерживает как индексированные, так и ассоциативные массивы):
// false if empty array $last = end($array); // null if empty array $last = !empty($array) ? end($array) : null;
Если вы хотите, чтобы функция утилиты не изменяла внутренний указатель:
function array_last($array) { if (empty($array)) { return null; } return end($value); }
Внутренний указатель исходного массива не изменяется, поскольку массив копируется.
Таким образом, следующая альтернатива на самом деле быстрее, поскольку она не копирует массив, она просто делает срез:
function array_last($array) { if (empty($array)) { return null; } foreach (array_slice($array, -1) as $value) { return $value; } }
Этот «foreach / return» является настройкой для эффективного получения первого (и здесь одного) элемента.
Наконец, самая быстрая альтернатива, но только для индексированных массивов:
$last = !empty($array) ? $array[count($array)-1] : null;
Что делать, если вы хотите получить последний элемент массива внутри цикла его массива?
Приведенный ниже код приведет к бесконечному циклу:
foreach ($array as $item) { $last_element = end($array); reset($array); if ($last_element == $item) { // something useful here } }
Решение, очевидно, просто для не ассоциативных массивов:
$last_element = $array[sizeof ($array) - 1]; foreach ($array as $key => $item) { if ($last_element == $item) { // something useful here } }
Почти на каждом языке с массивами вы не можете ошибиться с A [A.size-1]. Я не могу придумать пример языка с 1 базируемым массивом (в отличие от нуля).