Каков наилучший способ получить последний элемент массива без его удаления?

В порядке,

Я знаю все о 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 . Параметры, которые я буду тестировать:

  • параметр 1. $x = array_values(array_slice($array, -1))[0];
  • option 2. $x = array_slice($array, -1)[0];
  • option 3. $x = array_pop((array_slice($array, -1)));
  • option 4. $x = array_pop((array_slice($array, -1, 1)));
  • option 5. $x = end($array); reset($array); $x = end($array); reset($array);
  • option 6. $x = end((array_values($array)));
  • option 7. $x = $array[count($array)-1];
  • опция 8. $keys = array_keys($array); $x = $array[$keys[count($keys)-1]]; $keys = array_keys($array); $x = $array[$keys[count($keys)-1]];
  • option 9. $x = $array[] = array_pop($array);

Тестовые входы:

  • null = $array = null;
  • empty = $array = [];
  • last_null = $array = ["a","b","c",null];
  • auto_idx = $array = ["a","b","c","d"];
  • shuffle = $array = []; $array[1] = "a"; $array[2] = "b"; $array[0] = "c"; $array = []; $array[1] = "a"; $array[2] = "b"; $array[0] = "c";
  • 100 = $array = []; for($i=0;$i<100;$i++) { $array[] = $i; } $array = []; for($i=0;$i<100;$i++) { $array[] = $i; }
  • 100000 = $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 

Исходя из этого вывода, я делаю следующие выводы:

  • используйте более новую версию PHP, когда это возможно (duh)
  • для больших массивов варианты ограничены:
    • либо вариант 5. $x = end($array); reset($array); $x = end($array); reset($array);
    • или вариант 7. $x = $array[count($array)-1];
    • или вариант 9. $x = $array[] = array_pop($array);
  • для не-автоиндексированных массивов опции 7 и 9 не являются опцией

Лично мне не нравится по отношению к себе с внутренними указателями массива и предпочитаю решение в одном выражении. Поэтому рассказ, который я бы сам использовал:

  • для автоиндексированных массивов:
    • либо вариант 7. $x = $array[count($array)-1];
    • или вариант 9. $x = $array[] = array_pop($array);
  • для не-автоиндексированных массивов: (недействительно)
    • option 9. $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 базируемым массивом (в отличие от нуля).