540

Ok,

I know all about array_pop(), but that deletes the last element. How to get the last element of an array without deleting it?

Here's a bonus:

$array = array('a' => 'a', 'b' => 'b', 'c' => 'c');

or even

$array = array('a', 'b', 'c', 'd');
unset($array[2]);
echo $array[sizeof($array) - 1]; // Output: PHP Notice:  Undefined offset:  2 in - on line 4
Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
Theodore R. Smith
  • 21,848
  • 12
  • 65
  • 91
  • 13
    Believe it or not popping it and putting it back on is one of the fastest ways I benchmarked doing this. $val=$array[]=array_pop($array); echo $val; – user2782001 Jun 27 '16 at 16:36
  • 2
    This question resulted in many options. To help myself choose, I did some comparison of most notable / distinct options and shared the results [as a separate answer](http://stackoverflow.com/questions/3687358/whats-the-best-way-to-get-the-last-element-of-an-array-without-deleting-it/41795859#41795859). (:@user2782001 suggested my favorite so far in the comment above.:) Thanks to all for contributing! – pjvleeuwen Feb 05 '17 at 18:33
  • 2
    [@TheodoreRSmith](https://stackoverflow.com/users/430062/theodore-r-smith) When PHP 7.3 is released you could consider making ([this suggestion](https://stackoverflow.com/a/52509459/2799887) by [Quasimodo's clone](https://stackoverflow.com/users/3741589/quasimodos-clone) the 'accepted answer' (for your consideration)... – pjvleeuwen Oct 04 '18 at 11:55

33 Answers33

593

Try end:

$myLastElement = end($yourArray);

Note that this doesn't just return the last element of the passed array, it also modifies the array's internal pointer, which is used by current, each, prev, and next.

For PHP >= 7.3.0:

If you are using PHP version 7.3.0 or later, you can use array_key_last, which returns the last key of the array without modifying its internal pointer. So to get the last value, you can do:

$myLastElement = $yourArray[array_key_last($yourArray)];
Flimm
  • 136,138
  • 45
  • 251
  • 267
Iznogood
  • 12,447
  • 3
  • 26
  • 44
  • 1
    Awesome! Obviously I know about the manual (as i linked to it in my question) but it's a LOT of functions to parse and I missed that one. Thanks, bro. – Theodore R. Smith Sep 10 '10 at 18:42
  • @hopeseekr I linked the manual so you could read its entry for end() not because I taught you did not know about it :) And it helps others who will search here for the same question. Happy to have helped! – Iznogood Sep 10 '10 at 18:44
  • 2
    The problem with end($array) is that it modifies the internal pointer of the array to point to the last element, which could be an issue, depending on your implementation details. – Wade Tandy Sep 10 '10 at 18:44
  • 1
    The second answer totally doesn't work for key-based arraymaps. In fact, there's no good way except end() as far as I know. I've rescinded the acceptance of this answer until you remove the second part of your answer. – Theodore R. Smith Sep 10 '10 at 18:57
  • @hopeseekr edited one last time my answer. Anyways I always end() myself so that answer reflex more what I think. Hey thanks!! – Iznogood Sep 10 '10 at 18:59
  • 10
    @DavidMurdoch Perhaps, but it sure does churn the RAM and CPU, creating the temp array for the array values... – Theodore R. Smith May 05 '12 at 02:46
  • 14
    If your server is consuming too much RAM so that calling one simple extra function is a deal breaker, I suggest you re-examine your server's configuration and resources. – Chris Baker Jul 02 '12 at 19:16
  • 7
    `end(array_values())` will give a E_STRICT: "Only variables should be passed by reference" – kolypto Nov 29 '12 at 00:57
  • 37
    Add additional parenthesis to avoid the strict warning: `end((array_values($yourArray)))` – Daniel W. Mar 19 '14 at 14:04
  • 3
    For those who go right to the answers and usually don't read the whole question... Do yourself a favor and read the whole question... OP knows about the function to use array_pop() "I know all about array_pop()" But if you don't read until the end of the question, you might think that what is being discussed here is just the way to get the last element of an array regardless of deletion. Hope it can help some other going above the speed limit. – mimoralea Sep 03 '14 at 17:37
  • 1
    Only in PHP would the idiomatic inspection of an array element cause a side effect. – Keeth Jul 08 '15 at 17:48
  • end() expects parameter 1 to be array, null given – Yevgeniy Afanasyev Nov 19 '15 at 05:41
  • 1
    @YevgeniyAfanasyev Of course you need to pass the function a valid array. Not null! Check first if your array is, indeed, a array with http://php.net/manual/en/function.is-array.php – Iznogood Nov 30 '15 at 17:16
  • Well, after 5 1/2 years, someone posted a better answer. I'm changing my acceptance... – Theodore R. Smith Mar 13 '16 at 14:58
  • You don't need to call `end` if you iterate the array with `foreach`, as it uses it's own internal pointer. – Binar Web Apr 19 '18 at 09:42
  • 1
    `end(&array)` requires to pass array by reference, if you use it on on-the-fly-generated arrays it will throw a notice, like `end(explode(' ', $str))` – evilReiko Jul 01 '18 at 13:28
  • 1
    Since this is the highest votest answer at this time. Please note that recently (Dec 2018) a new option became available: `$array[array_key_last($array)];` ([as suggested](https://stackoverflow.com/a/52509459/2799887) by [Quasimodo's clone](https://stackoverflow.com/users/3741589/quasimodos-clone) ; available per PHP 7.3). – pjvleeuwen Jan 05 '19 at 14:50
  • 1
    Note that the argument / remark that a `reset()` solves the possible problem of modifying the internal pointer might not be true depending on your context. If you are relying on the internal pointer being in a particular state (e.g. because you are using it in some outer loop to traverse the array, than any method that moves the internal pointer can be a problem. `reset()` does not necessarily move the pointer to the state it was in before the call to `end()` (only if it was already at the start of the array before the call to `end()`. – pjvleeuwen Jan 05 '19 at 14:51
345

The many answers in this thread present us with many different options. To be able to choose from them I needed to understand their behavior and performance. In this answer I will share my findings with you, benchmarked against PHP versions 5.6.38, 7.2.10 and 7.3.0RC1 (expected Dec 13 2018).

The options (<<option code>>s) I will test are:

(functions mentioned: array_key_last , array_keys , array_pop , array_slice , array_values , count , end , reset)

The test inputs (<<input code>>s) to combine with:

  • 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";
  • 100 = $array = []; for($i=0;$i<100;$i++) { $array[] = $i; }
  • 100000 = $array = []; for($i=0;$i<100000;$i++) { $array[] = $i; }

For testing I will use the 5.6.38, 7.2.10 and 7.3.0RC1 PHP docker containers like:

sudo docker run -it --rm php:5.6.38-cli-stretch php -r '<<<CODE HERE>>>'

Each combination of the above listed <<option code>>s and <<input code>>s will be run on all versions of PHP. For each test run the following code snippet is used:

<<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<100;$j++){  <<option code>>  }}; $after=microtime(TRUE); echo "\n"; var_dump($x); echo round(($after-$before)/(100*100)*1000*1000*1000);

For each run this will var_dump the last retrieved last value of the test input and print the average duration of one iteration in femtoseconds (0.000000000000001th of a second).

The results are as follows:

/==========================================================================================================================================================================================================================================================================================================================================================================================================================\
||                                                                      ||                            T  E  S  T     I  N  P  U  T     -     5  .  6  .  3  8                            ||                             T  E  S  T     I  N  P  U  T     -     7  .  2  .  1  0                           ||                             T  E  S  T     I  N  P  U  T     -     7  .  3  .  0  R  C  1                     ||
||                                                                      ||          null |         empty |     last_null |      auto_idx |       shuffle |           100 |        100000 ||          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 |             - |             - |             - |             - |             - ||       W1 + W2 |            N1 |             - |             - |             - |             - |             - ||
||  2.  $x = array_slice($array, -1)[0];                                ||            W1 |            N1 |             - |             - |             - |             - |             - ||            W1 |            N1 |             - |             - |             - |             - |             - ||            W1 |            N1 |             - |             - |             - |             - |             - ||
||  3.  $x = array_pop((array_slice($array, -1)));                      ||       W1 + W3 |             - |             - |             - |             - |             - |             - ||  W1 + N2 + W3 |            N2 |            N2 |            N2 |            N2 |            N2 |            N2 ||  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 ||  W1 + N2 + W3 |            N2 |            N2 |            N2 |            N2 |            N2 |            N2 ||
||  5.  $x = end($array); reset($array);                                ||       W4 + W5 |             - |             - |             - |             - |             - |             - ||       W4 + W5 |            N2 |            N2 |            N2 |            N2 |            N2 |            N2 ||       W4 + W5 |             - |             - |             - |             - |             - |             - ||
||  6.  $x = end((array_values($array)));                               ||       W2 + W4 |             - |             - |             - |             - |             - |             - ||  W2 + N2 + W4 |             - |             - |             - |             - |             - |             - ||  W2 + N2 + W4 |            N2 |            N2 |            N2 |            N2 |            N2 |            N2 ||
||  7.  $x = $array[count($array)-1];                                   ||             - |            N3 |             - |             - |             - |             - |             - ||            W7 |            N3 |             - |             - |             - |             - |             - ||            W7 |            N3 |             - |             - |             - |             - |             - ||
||  8.  $keys = array_keys($array); $x = $array[$keys[count($keys)-1]]; ||            W6 |       N3 + N4 |             - |             - |             - |             - |             - ||       W6 + W7 |       N3 + N4 |             - |             - |             - |             - |             - ||       W6 + W7 |       N3 + N4 |             - |             - |             - |             - |             - ||
||  9.  $x = $array[] = array_pop($array);                              ||            W3 |             - |             - |             - |             - |             - |             - ||            W3 |             - |             - |             - |             - |             - |             - ||            W3 |             - |             - |             - |             - |             - |             - ||
|| 10.  $x = $array[array_key_last($array)];                            ||            F1 |            F1 |            F1 |            F1 |            F1 |            F1 |            F1 ||            F2 |            F2 |            F2 |            F2 |            F2 |            F2 |            F2 ||            W8 |            N4 |            F2 |            F2 |            F2 |            F2 |            F2 ||
||========================OPTIONS - VALUE RETRIEVED=====================++===============+===============+===============+===============+===============+===============+===============++===============+===============+===============+===============+===============+===============+===============++===============+===============+===============+===============+===============+===============+===============<|
||  1.  $x = array_values(array_slice($array, -1))[0];                  ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |    int(99999) ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |    int(99999) ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |    int(99999) ||
||  2.  $x = array_slice($array, -1)[0];                                ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |    int(99999) ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |    int(99999) ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |    int(99999) ||
||  3.  $x = array_pop((array_slice($array, -1)));                      ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |    int(99999) ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |    int(99999) ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |    int(99999) ||
||  4.  $x = array_pop((array_slice($array, -1, 1)));                   ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |    int(99999) ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |    int(99999) ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |    int(99999) ||
||  5.  $x = end($array); reset($array);                                ||          NULL |   bool(false) |          NULL | string(1) "d" | string(1) "c" |       int(99) |    int(99999) ||          NULL |   bool(false) |          NULL | string(1) "d" | string(1) "c" |       int(99) |    int(99999) ||          NULL |   bool(false) |          NULL | string(1) "d" | string(1) "c" |       int(99) |    int(99999) ||
||  6.  $x = end((array_values($array)));                               ||          NULL |   bool(false) |          NULL | string(1) "d" | string(1) "c" |       int(99) |    int(99999) ||          NULL |   bool(false) |          NULL | string(1) "d" | string(1) "c" |       int(99) |    int(99999) ||          NULL |   bool(false) |          NULL | string(1) "d" | string(1) "c" |       int(99) |    int(99999) ||
||  7.  $x = $array[count($array)-1];                                   ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "b" |       int(99) |    int(99999) ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "b" |       int(99) |    int(99999) ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "b" |       int(99) |    int(99999) ||
||  8.  $keys = array_keys($array); $x = $array[$keys[count($keys)-1]]; ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |    int(99999) ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |    int(99999) ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |    int(99999) ||
||  9.  $x = $array[] = array_pop($array);                              ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |    int(99999) ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |    int(99999) ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |    int(99999) ||
|| 10.  $x = $array[array_key_last($array)];                            ||           N/A |           N/A |           N/A |           N/A |           N/A |           N/A |           N/A ||           N/A |           N/A |           N/A |           N/A |           N/A |           N/A |           N/A ||           N/A |           N/A |           N/A |           N/A |           N/A |           N/A |           N/A ||
||=================OPTIONS - FEMTOSECONDS PER ITERATION=================++===============+===============+===============+===============+===============+===============+===============++===============+===============+===============+===============+===============+===============+===============++===============+===============+===============+===============+===============+===============+===============<|
||  1.  $x = array_values(array_slice($array, -1))[0];                  ||           803 |           466 |           390 |           384 |           373 |           764 |     1.046.642 ||           691 |           252 |           101 |           128 |            93 |           170 |        89.028 ||           695 |           235 |            90 |            97 |            95 |           188 |        87.991 ||
||  2.  $x = array_slice($array, -1)[0];                                ||           414 |           349 |           252 |           248 |           246 |           604 |     1.038.074 ||           373 |           249 |            85 |            91 |            90 |           164 |        90.750 ||           367 |           224 |            78 |            85 |            80 |           155 |        86.141 ||
||  3.  $x = array_pop((array_slice($array, -1)));                      ||           724 |           228 |           323 |           318 |           350 |           673 |     1.042.263 ||           988 |           285 |           309 |           317 |           331 |           401 |        88.363 ||           877 |           266 |           298 |           300 |           326 |           403 |        87.279 ||
||  4.  $x = array_pop((array_slice($array, -1, 1)));                   ||           734 |           266 |           358 |           356 |           349 |           699 |     1.050.101 ||           887 |           288 |           316 |           322 |           314 |           408 |        88.402 ||           935 |           268 |           335 |           315 |           313 |           403 |        86.445 ||
||  5.  $x = end($array); reset($array);                                ||           715 |           186 |           185 |           180 |           176 |           185 |           172 ||           674 |            73 |            69 |            70 |            66 |            65 |            70 ||           693 |            65 |            85 |            74 |            68 |            70 |            69 ||
||  6.  $x = end((array_values($array)));                               ||           877 |           205 |           320 |           337 |           304 |         2.901 |     7.921.860 ||           948 |           300 |           336 |           308 |           309 |           509 |    29.696.951 ||           946 |           262 |           301 |           309 |           302 |           499 |    29.234.928 ||
||  7.  $x = $array[count($array)-1];                                   ||           123 |           300 |           137 |           139 |           143 |           140 |           144 ||           312 |           218 |            48 |            53 |            45 |            47 |            51 ||           296 |           217 |            46 |            44 |            53 |            53 |            55 ||
||  8.  $keys = array_keys($array); $x = $array[$keys[count($keys)-1]]; ||           494 |           593 |           418 |           435 |           399 |         3.873 |    12.199.450 ||           665 |           407 |           103 |           109 |           114 |           431 |    30.053.730 ||           647 |           445 |            91 |            95 |            96 |           419 |    30.718.586 ||
||  9.  $x = $array[] = array_pop($array);                              ||           186 |           178 |           175 |           188 |           180 |           181 |           186 ||            83 |            78 |            75 |            71 |            74 |            69 |            83 ||            71 |            64 |            70 |            64 |            68 |            69 |            81 ||
|| 10.  $x = $array[array_key_last($array)];                            ||           N/A |           N/A |           N/A |           N/A |           N/A |           N/A |           N/A ||           N/A |           N/A |           N/A |           N/A |           N/A |           N/A |           N/A ||           370 |           223 |            49 |            52 |            61 |            57 |            52 ||
 \=========================================================================================================================================================================================================================================================================================================================================================================================================================/ 

The above mentioned Fatal, Warning and Notice codes translate as:

F1 = Fatal error: Call to undefined function array_key_last() in Command line code on line 1
F2 = Fatal error: Uncaught Error: Call to undefined function array_key_last() in Command line code:1
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
W7 = Warning: count(): Parameter must be an array or an object that implements Countable in Command line code on line 1
W8 = Warning: array_key_last() 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

Based on this output I draw the following conclusions:

  • newer versions of PHP perform better with the exception of these options that became significantly slower:
    • option .6. $x = end((array_values($array)));
    • option .8. $keys = array_keys($array); $x = $array[$keys[count($keys)-1]];
  • these options scale best for very large arrays:
    • option .5. $x = end($array); reset($array);
    • option .7. $x = $array[count($array)-1];
    • option .9. $x = $array[] = array_pop($array);
    • option 10. $x = $array[array_key_last($array)]; (since PHP 7.3)
  • these options should only be used for auto-indexed arrays:
    • option .7. $x = $array[count($array)-1]; (due to use of count)
    • option .9. $x = $array[] = array_pop($array); (due to assigning value losing original key)
  • this option does not preserve the array's internal pointer
    • option .5. $x = end($array); reset($array);
  • this option is an attempt to modify option .5. to preserve the array's internal pointer (but sadly it does not scale well for very large arrays)
    • option .6. $x = end((array_values($array)));
  • the new array_key_last function seems to have none of the above mentioned limitations with the exception of still being an RC at the time of this writing (so use the RC or await it's release Dec 2018):
    • option 10. $x = $array[array_key_last($array)]; (since PHP 7.3)

A bit depending on whether using the array as stack or as queue you can make variations on option 9.

pjvleeuwen
  • 4,215
  • 1
  • 18
  • 31
  • If you find a particular option to be missing you can test it yourself by copy-pasting the above code snippets together, comparing it against a previously tested option. To add an option to this list would be retesting all combinations for comparable performance results. If you have a particular option that you think should be added, please drop a comment, I intent to add it then (though it may take some time). – pjvleeuwen Feb 04 '17 at 13:04
  • 1
    Very great answer, one comment though: for associative arrays option 9 cannot be used too, because we are assigning back to an auto-indexed key instead of the previous key name. – Gras Double Jul 26 '17 at 05:52
  • @GrasDouble Thanks, and damn, you are right. I have not used PHP much after writing this answer :-$. Do we have (suspected) high-performing options for large associative arrays? – pjvleeuwen Jul 26 '17 at 09:34
  • The fastest by far is to simply use `end()` (unless the array is copied, see https://github.com/laravel/framework/pull/20261). If you want to preserve the internal pointer, or less worst choice when the array is copied: `foreach (array_slice($array, -1) as $item) { }`, the `foreach` saves a function call. – Gras Double Jul 26 '17 at 09:58
  • I really like your idea of taking the various answer and comparing them, especially perfomance-wise. Unfortunately, SO is not very user-friendly with displaying tables. – Sybille Peters Jan 12 '18 at 12:25
  • Great stuff, thank you! What did you produce that formidable table with? – Sz. Feb 12 '18 at 00:05
  • The biggest problem here with option 7 is that it is assuming that all the keys are sequential, with no jumps and all numerical. It takes only a `[10 => 'whatever']` to break it with undefined index. – Victor Schröder Feb 20 '18 at 22:14
  • 4
    Nice summary! Please add my [answer](https://stackoverflow.com/questions/3687358/whats-the-best-way-to-get-the-last-element-of-an-array-without-deleting-it/52509459#52509459) using the new PHP 7.3. function `$array[array_key_last($array)];` to your benchmark. And please give me some notification when done. I'ld like to see the performance results in comparison. – Pinke Helga Sep 26 '18 at 03:55
  • 2
    @sz it was mainly produced with a lot of stubbornness and patience but the general selection and multi-line edit functions of Sublime text editor helped. regenerating it took almost a day, so if I need to do it again I will probably write something that converts the output of all 210 docker executions to a table automatically :-) – pjvleeuwen Sep 29 '18 at 20:07
  • 1
    @quasimodos-clone I regenerated the whole table based on latest released PHP 5, 7 and your RC. I suppose we will want to generate it again coming December when it is actually released. Thanks for bringing this new function to everybody's attention. – pjvleeuwen Sep 29 '18 at 20:08
  • Best answer, alway the answer for a problem depends on the context of the problem. Sometimes you may need readability sometimes performance sometimes warning, etc. – Diego Andrés Díaz Espinoza Oct 18 '18 at 13:52
  • Great answer! Also very revealing on how silly php is :) python: some_list[-1] the end :D – veryxcit Aug 18 '20 at 20:10
  • I love PHP (with Laravel), but every now and then I miss pythonean simplicity. Last element? `myList[-1]`. Last character? `myString[-1]`. – s3c Jan 05 '21 at 14:24
  • I suppose array_reverse($array)[0] has been disqualified as being expected to be the slowest solution from the start but it would be interesting to have a comparison of its performance in the list. – Bevelopper Mar 04 '21 at 13:49
  • This answer provides a metric ton of completely useless information. And could have been drastically shorter if only explained the concept of complexity to PHP folks. And therefore discard all O(n) solutions without any useless "tests". – Your Common Sense May 10 '22 at 13:56
218

Short and sweet.

I came up with solution to remove error message and preserve one-liner form and efficient performance:

$lastEl = array_values(array_slice($array, -1))[0];

-- previous solution

$lastEl = array_pop((array_slice($array, -1)));

Note: The extra parentheses are needed to avoid a PHP Strict standards: Only variables should be passed by reference.

rolacja
  • 2,381
  • 1
  • 13
  • 12
  • 1
    Greet answer, but adding the extra parentheses feels a little hackisch. Also phpStorm will mark this as an error. Extra info for adding extra parentheses (http://phpsadness.com/sad/51). To overcome the error, you could make this a '2-liner': `$array = array_slice($array, -1); $lastEl = array_pop($array);` Personally i think this is better (without the parser 'bug') – Maurice Jun 23 '16 at 09:38
  • You can stil get it as one-liner and without additional variable: $lastEl = array_pop($lastEl = (array_slice($array, -1))); – rolacja Jun 23 '16 at 15:56
  • 3
    You can use dereferencing like this: array_slice($array, -1)[0] – Vikash Oct 04 '16 at 12:24
  • 1
    You can't if you have strings as index in array – rolacja Oct 08 '16 at 06:45
  • In PHP7 a warning (`E_NOTICE` as PHP7 has no `E_STRICT`) will be emitted even if you use extra parantheses. – Tgr Oct 22 '16 at 03:42
  • 3
    This answer still needs at least two checks to avoid PHP notices. **1.** check if the `array_size() > 1` **2.** Check if the array is actually an array. _I still stick to the answer by @Iznogood as PHP's in-built `end()` function already does all the hard-work in a more efficient manner._ – Ema4rl Dec 04 '16 at 23:43
  • why not just use the end() function? – jhonatan teixeira Aug 19 '18 at 14:36
  • @jhonatanteixeira if you are using the arrays internal pointer for something else in a wider context you might want to avoid the use of `end()`... – pjvleeuwen Oct 04 '18 at 11:51
43

What's wrong with array_slice($array, -1)? (See Manual: http://us1.php.net/array_slice)

array_slice() returns an array. Probably not what you are looking for. You want the element.

Stoutie
  • 1,944
  • 1
  • 21
  • 17
  • 28
    Use `array_slice($array, -1)[0]` to get the element. – Pang Oct 19 '15 at 04:28
  • 3
    This is the answer. "end" Changing the internal pointer of the array? Asking for trouble, and very hard to read! – Gerard ONeill Dec 18 '15 at 15:03
  • Love this approach, although as @Pang points out, it's not quite complete. `reset(array_slice($array, -1))` is another approach (that won't cause an error if `array_slice()` returns anything "smaller" than a single-element array) – rinogo Feb 09 '16 at 16:56
  • The best approach as you can directly modify the element: `array_slice($array, -1)[0] = "";` – Lorenzo Lapucci Nov 16 '16 at 10:14
22

If you don't care about modifying the internal pointer (the following lines support both indexed and associative arrays):

// false if empty array
$last = end($array);

// null if empty array
$last = !empty($array) ? end($array) : null;


If you want an utility function that doesn't modify the internal pointer (because the array is passed by value to the function, so the function operates on a copy of it):

function array_last($array) {
    if (empty($array)) {
        return null;
    }
    return end($array);
}


Though, PHP produces copies "on-the-fly", i.e. only when actually needed. As the end() function modifies the array, internally a copy of the whole array (minus one item) is generated.


Therefore, I would recommend the following alternative that is actually faster, as internally it doesn't copy the array, it just makes a slice:

function array_last($array) {
    if (empty($array)) {
        return null;
    }
    foreach (array_slice($array, -1) as $value) {
        return $value;
    }
}

Additionally, the "foreach / return" is a tweak for efficiently getting the first (and here single) item.


Finally, the fastest alternative but for indexed arrays (and without gaps) only:

$last = !empty($array) ? $array[count($array)-1] : null;


For the record, here is another answer of mine, for the array's first element.

Gras Double
  • 15,901
  • 8
  • 56
  • 54
  • you provide 2 alternative implementations for an `array_last` function. For the first you state that the `$array` is copied and for the second that it is not copied. Where is the difference / why is it copied in the first implementation and not in the second? – pjvleeuwen Oct 04 '18 at 11:44
  • 1
    @PaulvanLeeuwen I understood why you got confused. I tried to [clarify the answer](https://stackoverflow.com/posts/45333947/revisions), is it better? – Gras Double Oct 05 '18 at 20:27
21

One way to avoid pass-by-reference errors (eg. "end(array_values($foo))") is to use call_user_func or 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))));
Warbo
  • 2,611
  • 1
  • 29
  • 23
  • Great approach! (insert the standard 'This should be the accepted answer' here) – Typo Oct 17 '13 at 08:54
  • 3
    Or just add an extra paranthesis. Shorter and sweeter: `end((array_values($yourArray)))` – Dzhuneyt Sep 02 '14 at 14:40
  • 6
    The extra parenthesis trick relies on a bug in PHP, and that approach no longer works in later versions of PHP (or at least, not in PHP 7). – Matt Browne May 06 '16 at 19:29
  • 1
    And the `call_user_func` trick doesn't work in PHP 7 either. I think you're stuck with creating a temporary variable. – Matt Browne May 06 '16 at 19:34
13

As of PHP version 7.3 the functions array_key_first and array_key_last has been introduced.

Since arrays in PHP are not strict array types, i.e. fixed sized collections of fixed sized fields starting at index 0, but dynamically extended associative array, the handling of positions with unknown keys is hard and workarounds do not perform very well. In contrast real arrays would be internally addressed via pointer arithmethics very rapidly and the last index is already known at compile-time by declaration.

At least the problem with the first and last position is solved by builtin functions now since version 7.3. This even works without any warnings on array literals out of the box:

$first = array_key_first( [1, 2, 'A'=>65, 'B'=>66, 3, 4 ] );
$last  = array_key_last ( [1, 2, 'A'=>65, 'B'=>66, 3, 4 ] );

Obviously the last value is:

$array[array_key_last($array)];
Pinke Helga
  • 6,378
  • 2
  • 22
  • 42
  • 2
    Thanks for bringing this to everybody's attention. For those who are eager to use this: please not that this is a RC at the moment of this writing. It is scheduled for release Dec 2018. – pjvleeuwen Sep 30 '18 at 19:23
  • 1
    This is great news. I've just posted a polyfill/shim in [my answer below](https://stackoverflow.com/a/52673279/308145) so people can start using this syntax right away. – Mark Thomson Oct 05 '18 at 21:10
  • This deserves more upvotes since it was posted first. This `array_key_last ` solution was [also added in May 2022](https://stackoverflow.com/revisions/3687368/8) to [the top-voted answer](https://stackoverflow.com/a/3687368/) by someone else. IMO without a nod to this is unfair even though this answer itself is years old and kind of at the bottom now. – joeljpa Aug 25 '23 at 11:11
12

I need this quite often to deal with stacks, and i always find myself baffled that there's no native function that does it without manipulating the array or its internal pointer in some form.

So i usually carry around a util function that's also safe to use on associative arrays.

function array_last($array) {
    if (count($array) < 1)
        return null;

    $keys = array_keys($array);
    return $array[$keys[sizeof($keys) - 1]];
}
thrau
  • 2,915
  • 3
  • 25
  • 32
  • 1
    Good news, they are making it a native function :-) You can keep an eye on it's release planning here: https://wiki.php.net/todo/php73 (expected Dec 13 2018 at the time of this writing). – pjvleeuwen Oct 04 '18 at 11:40
11

To get the last element of an array, use:

$lastElement = array_slice($array, -1)[0];

Benchmark

I iterated 1,000 times, grabbing the last element of small and large arrays that contained 100 and 50,000 elements, respectively.

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...

I used PHP Version 5.5.32.

Westy92
  • 19,087
  • 4
  • 72
  • 54
  • what about using $array[array_keys($array)[count(array_keys($array))-1] ]? – user2782001 Jun 27 '16 at 15:59
  • hmm..array_keys seems to scale pretty poorly. – user2782001 Jun 27 '16 at 16:08
  • using array_keys: I got .003 for the small array and 6.6 for the large. Using $temp=array_combine(array_fill(0,count($ar),0),$ar);$temp[count($temp)-1]; was 3.1 for the large and Using array_values($ar)[count($ar)-1] was 3.3 for the large. – user2782001 Jun 27 '16 at 16:20
  • 1
    It's actually crazy faster for the large array (0.0002) to pop the item and put it back on...$val=$ar[]=$array_pop($ar); – user2782001 Jun 27 '16 at 16:31
  • 1
    @Westy92 Your units seem wrong on the benchmark. The smallest number you give is 0.00031... _microseconds_ which is about 0.3 nanoseconds. That would mean that your test took one clock tick to run if you have a newish computer. I'm guessing you either meant _milliseconds_ or possibly even _seconds_. – cesoid Jul 18 '16 at 20:12
  • Note that function array dereferencing is PHP 5.4+. – Tgr Oct 22 '16 at 02:56
  • 1
    The values are clearly several orders of magnitude wrong. Why the focus on performance anyway? – istepaniuk May 16 '18 at 08:29
11

untested: wouldn't this work?

<?php
$last_element=end(array_values($array));
?>

Since the array returned by array_values is fleeting, no-one cares if it's pointer is reset.

and if you need the key to go with it I guess you'd do:

<?php
$last_key=end(array_keys($array));
?>
TecBrat
  • 3,643
  • 3
  • 28
  • 45
  • 2
    Question: why untested? You just open a terminal and type: `php -r '$array=[1,2,3];echo end(array_values($array))."\n";'` BTW it throws a notice, so it's not the best way: Only variables should be passed by reference in Command line code on line 1 – soger Oct 26 '20 at 12:44
6

end() will provide the last element of an array

$array = array('a' => 'a', 'b' => 'b', 'c' => 'c');
echo end($array); //output: c

$array1 = array('a', 'b', 'c', 'd');
echo end($array1); //output: d
Ajith
  • 194
  • 2
  • 8
5

One more possible solution...

$last_element = array_reverse( $array )[0];
Pang
  • 9,564
  • 146
  • 81
  • 122
  • Not working on associative arrays does not seem like enough reason to downvote to me. Quality-wise this answer is not worse then many other answers to this question. I do not understand why I see at least 2 downvotes at this time. (score of -2). Anyways, upvote for me, it is not that bad. – pjvleeuwen Apr 12 '17 at 20:57
5

How about this?

Eg-

$arr = [1,2,3];
$lastElem = count($arr) ? $arr[count($arr) - 1] : null;
Koushik Das
  • 9,678
  • 3
  • 51
  • 50
4
$lastValue = end(array_values($array))

No modification is made to $array pointers. This avoids the

reset($array)

which might not be desired in certain conditions.

Vihaan Verma
  • 12,815
  • 19
  • 97
  • 126
4

For me:

$last = $array[count($array) - 1];

With associatives:

$last =array_values($array)[count($array - 1)]
Mirko Pagliai
  • 1,220
  • 1
  • 19
  • 36
4

How about:

current(array_slice($array, -1))
  • works for associative arrays
  • works when $array == [] (returns false)
  • doesn't affect the original array
Bouke Versteegh
  • 4,097
  • 1
  • 39
  • 35
  • I like this, because you don't have to pass by reference. So it can be used for the oft-asked question "How do I get the last element of a delimited string?", by using current(array_slice(explode('|', 'a|b|c|d'), -1)) – Tac Tacelosky Sep 22 '21 at 00:13
3

The top answers are great, but as mentioned by @paul-van-leeuwen and @quasimodos-clone, PHP 7.3 will introduce two new functions to solve this problem directly - array_key_first() and array_key_last().

You can start using this syntax today with the following polyfill (or shim) functions.

// Polyfill for array_key_last() available from PHP 7.3
if (!function_exists('array_key_last')) {
  function array_key_last($array) {
    return array_slice(array_keys($array),-1)[0];
  }
}

// Polyfill for array_key_first() available from PHP 7.3
if (!function_exists('array_key_first')) {
  function array_key_first($array) {
    return array_slice(array_keys($array),0)[0];
  }
}

// Usage examples:
$first_element_key   = array_key_first($array);
$first_element_value = $array[array_key_first($array)];

$last_element_key    = array_key_last($array);
$last_element_value  = $array[array_key_last($array)];

Caveat: This requires PHP 5.4 or greater.

Mark Thomson
  • 739
  • 5
  • 12
2

To do this and avoid the E_STRICT and not mess with the array's internal pointer you can use:

function lelement($array) {return end($array);}

$last_element = lelement($array);

lelement only works with a copy so it doesn't affect the array's pointer.

Damiene
  • 280
  • 3
  • 9
2

For getting the last value from Array :

array_slice($arr,-1,1) ;

For Removing last value form array :

array_slice($arr,0,count($arr)-1) ;
Rishabh
  • 546
  • 5
  • 8
  • 1
    `array_slice($arr,-1,1)` will result in another array with length 1, not the last element – Vic Jan 19 '16 at 08:01
  • Let's take a example : `$a=array("red","green","blue","yellow","brown"); print_r(array_slice($a,-1,1)); ` Result: `Array ( [0] => brown ) ` – Rishabh Jan 19 '16 at 14:39
2

Another solution:

$array = array('a' => 'a', 'b' => 'b', 'c' => 'c');
$lastItem = $array[(array_keys($array)[(count($array)-1)])];
echo $lastItem;
2

As of PHP 7.3, array_key_last is available

$lastEl = $myArray[array_key_last($myArray)];
divaka
  • 593
  • 7
  • 12
2

You will get last element from an array easily by using below logic

$array = array('a', 'b', 'c', 'd');
echo ($array[count($array)-1]);

Not only last element but you can also get second last, third last and so on by using below logic.

for second last element you have to pass just number 2 in the above statement for example:
echo ($array[count($array)-2]);

Amzad Khan
  • 121
  • 1
  • 6
1

Simply: $last_element = end((array_values($array)))

Doesn't reset the array and doesn't gives STRICT warnings.

PS. Since the most voted answer still hasn't the double parenthesis, I submitted this answer.

Daan
  • 7,685
  • 5
  • 43
  • 52
1

I think this is a slight improvement on all the existing answers:

$lastElement = count($array) > 0 ? array_values(array_slice($array, -1))[0] : null;
  • Performs better than end() or solutions using array_keys(), especially with large arrays
  • Won't modify the array's internal pointer
  • Won't try to access an undefined offset for empty arrays
  • Will work as expected for empty arrays, indexed arrays, mixed arrays, and associative arrays
Adelmar
  • 2,073
  • 2
  • 20
  • 20
1

Nowadays, I'd prefer always having this helper, as suggested at an php.net/end answer.

<?php
function endc($array) {
    return end($array);
}

$items = array('one','two','three');
$lastItem = endc($items); // three
$current = current($items); // one
?>

This will always keeps the pointer as it is and we will never have to worry about parenthesis, strict standards or whatever.

giovannipds
  • 2,860
  • 2
  • 31
  • 39
1

Most solutions here are unreliable for unassociated arrays, because if we have an unassociated array with the last element being false, then end and current(array_slice($array, -1)) will also return false so we can't use false as an indicator of an empty unassociated array.

// end returns false form empty arrays
>>> $arr = []
>>> end($arr)
=> false

// last element is false, so end returns false,
// now we'll have a false possitive that the array is empty
>>> $arr = [1, 2, 3, false]
>>> end($arr)
=> false

>>> $arr = [1, 2, 3, false, 4]
>>> end($arr)
=> 4

Same goes for current(array_slice($arr, -1)):

// returns false form empty arrays
>>> $arr = []
>>> current(array_slice($arr, -1))
=> false

// returns false if last element is false
>>> $arr = [1, 2, 3, false]
>>> current(array_slice($arr, -1))
=> false

>>> $arr = [1, 2, 3, false, 4]
>>> current(array_slice($arr, -1))
=> 4

Best option is to use array_key_last which is available for PHP >= 7.3.0 or for older versions, we use count to get the last index (only for unassociated arrays):

// returns null for empty arrays
>>> $arr = []
>>> array_key_last($arr)
=> null

// returns last index of the array
>>> $arr = [1, 2, 3, false]
>>> array_key_last($arr)
=> 3

// returns last index of the array
>>> $arr = [1, 2, 3, false, 4]
>>> array_key_last($arr)
=> 4

For older versions, we can use count:

>>> $arr = []
>>> if (count($arr) > 0) $arr[count($arr) - 1]
// No excecution

>>> $arr = [1, 2, 3, false]
>>> if (count($arr) > 0) $arr[count($arr) - 1]
=> false

>>> $arr = [1, 2, 3, false, 4]
>>> if (count($arr) > 0) $arr[count($arr) - 1]
=> 4

That's all for unassociated arrays. If we are sure that we have associated arrays, then we can use end.

Christos Lytras
  • 36,310
  • 4
  • 80
  • 113
0

Note: For (PHP 7 >= 7.3.0) we can use array_key_last — Gets the last key of an array

array_key_last ( array $array ) : mixed

Ref: http://php.net/manual/en/function.array-key-last.php

lokender singh
  • 829
  • 9
  • 18
-1
$file_name_dm =  $_FILES["video"]["name"];    

                           $ext_thumb = extension($file_name_dm);

                            echo extension($file_name_dm); 
function extension($str){
    $str=implode("",explode("\\",$str));
    $str=explode(".",$str);
    $str=strtolower(end($str));
     return $str;
}
Hussy Borad
  • 626
  • 5
  • 20
-1

Use the end() function.

$array = [1,2,3,4,5];
$last = end($array); // 5
Brian Berneker
  • 571
  • 6
  • 6
-1

What if you want to get the last element of array inside of the loop of it's array?

The code below will result into an infinite loop:

foreach ($array as $item) {
 $last_element = end($array);
 reset($array);
 if ($last_element == $item) {
   // something useful here
 }
}

The solution is obviously simple for non associative arrays:

$last_element = $array[sizeof ($array) - 1];
foreach ($array as $key => $item) {
 if ($last_element == $item) {
   // something useful here
 }
}
Jon Egerton
  • 40,401
  • 11
  • 97
  • 129
Vadim Podlevsky
  • 181
  • 1
  • 9
  • 2
    I know about end() and reset() functions. My comment was related to loops like foreach or while where you cannot use these functions because reset function resets the inner pointer of an array which is used in the loop for iteration. Sorry for that, the question was more simple, I just wanted to give more advanced situation I came across in my project. Best regards. – Vadim Podlevsky Jan 28 '13 at 12:45
  • This is wrong in many ways (arrays with duplicates, non-strict comparison...) and in any case not really related to the question. – Tgr Oct 22 '16 at 02:54
  • use the end($array) function to get the last element, why you unnecessarily using loops? – Mahak Choudhary Jan 15 '19 at 05:41
  • 1
    @MahakChoudhary My comment is an addition to "how to get last element of array if you are doing some manipulations already inside a loop of this array. Using end() will reset the innver pointer and break iteration loop. Cheers! – Vadim Podlevsky Oct 12 '19 at 22:51
-3

my simple solution, pretty and easy to understand.

array_reverse($array)[0];
UkFLSUI
  • 5,509
  • 6
  • 32
  • 47
Alper Aydingül
  • 251
  • 1
  • 9
-3

array_values(array_reverse($array))[0] works in all those situations.

JoeRaid
  • 107
  • 1
  • 10
-4

In almost every language with arrays you can't really go wrong with A[A.size-1]. I can't think of an example of a language with 1 based arrays (as opposed to zero based).

Aaron Anodide
  • 16,906
  • 15
  • 62
  • 121