Qual é a melhor maneira de obter o último elemento de uma matriz sem excluí-lo?

427

Está bem,

Eu sei tudo sobre array_pop(), mas isso exclui o último elemento. Qual é a melhor maneira de obter o último elemento de uma matriz sem excluí-lo?

EDIT: Aqui está um bônus:

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

ou mesmo

$array = array('a', 'b', 'c', 'd');
unset($array[2]);
echo $array[sizeof($array) - 1]; // Output: PHP Notice:  Undefined offset:  2 in - on line 4
Theodore R. Smith
fonte
11
Acredite ou não, e colocá-lo de volta é uma das maneiras mais rápidas de comparar isso. $ val = $ array [] = array_pop ($ array); eco $ val;
user2782001
2
Esta pergunta resultou em muitas opções. Para me ajudar a escolher, fiz uma comparação das opções mais notáveis ​​/ distintas e compartilhei os resultados como uma resposta separada . (: @ user2782001 sugeriu o meu favorito até agora no comentário acima. :) Obrigado a todos por contribuírem!
Paul van Leeuwen
1
@TheodoreRSmith Quando o PHP 7.3 é liberado você poderia considerar fazer ( esta sugestão por clone de Quasimodo a 'resposta aceita' (para sua consideração) ...
Paul van Leeuwen

Respostas:

176

As muitas respostas neste tópico nos apresentam muitas opções diferentes. Para poder escolher entre eles, eu precisava entender seu comportamento e desempenho. Nesta resposta que eu vou compartilhar minhas descobertas com você, por referência à informação versões do PHP 5.6.38, 7.2.10e 7.3.0RC1( espera 13 dezembro, 2018 ).

As opções <<option code>>que testarei são:

(funções mencionadas: array_key_last , array_keys , array_pop , array_slice , array_values , count , end , reset )

As entradas de teste <<input code>>para combinar com:

  • null =$array = null;
  • vazio =$array = [];
  • last_null =$array = ["a","b","c",null];
  • auto_idx =$array = ["a","b","c","d"];
  • aleatório =$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; }

Para testar que irá usar o 5.6.38, 7.2.10e 7.3.0RC1 recipientes docker PHP como:

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

Cada combinação dos <<option code>>s listados acima <<input code>>será executada em todas as versões do PHP. Para cada execução de teste, o seguinte trecho de código é usado:

<<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);

Para cada execução, isso fará com que var_dump o último valor recuperado da entrada de teste e imprima a duração média de uma iteração em femtossegundos (0,000000000000001º de segundo).

Os resultados são os seguintes:

/==========================================================================================================================================================================================================================================================================================================================================================================================================================\
||                                                                      ||                            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 ||
 \=========================================================================================================================================================================================================================================================================================================================================================================================================================/ 

O acima mencionado F atal, W Arning e N Otice códigos traduzir como:

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

Com base nesta saída, tirei as seguintes conclusões:

  • as versões mais recentes do PHP têm melhor desempenho, com exceção dessas opções que se tornaram significativamente mais lentas:
    • opção .6. $x = end((array_values($array)));
    • opção .8. $keys = array_keys($array); $x = $array[$keys[count($keys)-1]];
  • essas opções são dimensionadas melhor para matrizes muito grandes:
    • opção .5. $x = end($array); reset($array);
    • opção .7. $x = $array[count($array)-1];
    • opção .9. $x = $array[] = array_pop($array);
    • opção 10. $x = $array[array_key_last($array)]; (desde PHP 7.3)
  • essas opções devem ser usadas apenas para matrizes indexadas automaticamente :
    • opção .7. $x = $array[count($array)-1];(devido ao uso decount)
    • opção .9. $x = $array[] = array_pop($array);(devido à atribuição de valor à perda da chave original)
  • essa opção não preserva o ponteiro interno da matriz
    • opção .5. $x = end($array); reset($array);
  • esta opção é uma tentativa de modificar a opção .5. para preservar o ponteiro interno da matriz (mas, infelizmente, ela não escala bem para matrizes muito grandes)
    • opção .6. $x = end((array_values($array)));
  • a nova array_key_lastfunção parece não ter nenhuma das limitações mencionadas acima, com exceção de ainda ser um RC no momento da redação deste documento (portanto, use o RC ou aguarde o lançamento em dezembro de 2018):
    • opção 10. $x = $array[array_key_last($array)]; (desde PHP 7.3)

Um pouco, dependendo do uso da matriz como pilha ou fila, você pode fazer variações na opção 9.

Paul van Leeuwen
fonte
Se você encontrar uma opção em particular, pode testá-la copiando e colando os trechos de código acima juntos, comparando-os com uma opção testada anteriormente. Adicionar uma opção a esta lista seria testar novamente todas as combinações para obter resultados de desempenho comparáveis. Se você tem uma opção específica que acha que deve ser adicionada, envie um comentário, pretendo adicioná-lo (embora possa levar algum tempo).
Paul van Leeuwen
1
Resposta muito boa, porém, um comentário: para matrizes associativas, a opção 9 também não pode ser usada, porque estamos atribuindo de volta a uma chave indexada automaticamente em vez do nome da chave anterior.
Gras Double
1
Bom resumo! Por favor, adicione minha resposta usando o novo PHP 7.3. função $array[array_key_last($array)];para sua referência. E, por favor, me dê alguma notificação quando terminar. Gostaria de ver os resultados de desempenho em comparação.
clone de Quasimodo
2
O @sz foi produzido principalmente com muita teimosia e paciência, mas as funções de seleção geral e edição de várias linhas do editor de texto sublime ajudaram. regenerando que levou quase um dia, por isso, se eu preciso fazê-lo novamente eu provavelmente escrever algo que converte a saída de todos os 210 execuções docker a uma tabela automaticamente :-)
Paul van Leeuwen
1
@ quasimodos-clone Regenerei toda a tabela com base no PHP 5, 7 mais recente e no seu RC. Suponho que desejaremos gerá-lo novamente em dezembro, quando for realmente lançado. Obrigado por trazer esta nova função à atenção de todos.
Paul van Leeuwen 29/09
487

Tentar

$myLastElement = end($yourArray);

Para redefini-lo (obrigado @hopeseekr):

 reset($yourArray);

Link para o manual

@ David Murdoch adicionou: $myLastElement = end(array_values($yourArray));// and now you don't need to call reset(). Em E_STRICT, isso produz o aviso

Strict Standards: Only variables should be passed by reference

Obrigado o_O Tync e a todos!

Iznogood
fonte
38
Use $myLastElement = end(array_values($yourArray));e agora você não precisa ligar reset().
David Murdoch
5
@DavidMurdoch Talvez, mas com certeza faz agitar a memória RAM e CPU, criando a matriz temporário para os valores da matriz ...
Theodore R. Smith
12
Se o seu servidor estiver consumindo muita memória RAM, de modo que chamar uma função extra simples seja uma quebra de negócio, sugiro que você examine novamente a configuração e os recursos do servidor.
Chris Baker
3
end(array_values())dará um E_STRICT: "Somente variáveis ​​devem ser passadas por referência"
kolypto
32
Adicionar parêntese adicional para evitar o aviso estrita:end((array_values($yourArray)))
Daniel W.
212

Curto e grosso.

Eu vim com a solução para remover a mensagem de erro e preservar a forma de uma linha e o desempenho eficiente:

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

- solução anterior

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

Nota: Os parênteses extras são necessários para evitar a PHP Strict standards: Only variables should be passed by reference.

rolacja
fonte
31
Após exatamente 5 anos, 6 meses e 2 dias, você enviou uma resposta mais superior !! Obrigado! e obrigado Stack Overflow !!
Theodore R. Smith
1
Cumprimente a resposta, mas adicionar parênteses extras parece um pouco hackisch. O phpStorm também marcará isso como um erro. Informações adicionais para adicionar parênteses extras ( phpsadness.com/sad/51 ). Para superar o erro, você pode fazer um '2-liner': $array = array_slice($array, -1); $lastEl = array_pop($array);Pessoalmente eu acho que isso é melhor (sem o 'bug' parser)
Maurice
3
Você pode usar a desreferenciação como esta: array_slice ($ array, -1) [0]
Vikash
1
Você não pode se você tem strings como índice em conjunto
rolacja
3
Essa resposta ainda precisa de pelo menos duas verificações para evitar avisos do PHP. 1. verifique se o array_size() > 1 2. Verifique se o array é realmente um array. Ainda mantenho a resposta de @Iznogood, pois a end()função incorporada do PHP já faz todo o trabalho duro de uma maneira mais eficiente.
Ema4rl
37

O que há de errado array_slice($array, -1)? (Consulte o manual: http://us1.php.net/array_slice )

array_slice()retorna uma matriz. Provavelmente não é o que você está procurando. Você quer o elemento

Stoutie
fonte
21
Use array_slice($array, -1)[0]para obter o elemento
Pang
2
Essa é a resposta. "end" Alterando o ponteiro interno da matriz? Pedindo problemas, e muito difícil de ler!
precisa
Adore essa abordagem, embora, como a @Pang ressalte, ela não esteja completa. reset(array_slice($array, -1))é uma outra abordagem (que não causa um erro se array_slice()retorna nada "menor" do que uma matriz de elemento único)
rinogo
A melhor abordagem para modificar diretamente o elemento:array_slice($array, -1)[0] = "";
HAlex 16/16
20

Uma maneira de evitar erros de passagem por referência (por exemplo, "end (array_values ​​($ foo))") é usar call_user_func ou 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
fonte
Ótima abordagem! (insira o padrão 'Esta deve ser a resposta aceita' aqui) #
Typo 17/10
3
Ou apenas adicione uma parêntese extra. Mais curto e mais doce:end((array_values($yourArray)))
Dzhuneyt 02/02
4
O truque extra entre parênteses se baseia em um bug no PHP, e essa abordagem não funciona mais em versões posteriores do PHP (ou pelo menos, não no PHP 7).
Matt Browne
1
E o call_user_functruque também não funciona no PHP 7. Eu acho que você está preso com a criação de uma variável temporária.
Matt Browne
15

Se você não se preocupa em modificar o ponteiro interno (suporta matrizes indexadas e associativas):

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

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


Se você deseja uma função de utilitário que não modifique o ponteiro interno (porque a matriz é passada por valor e a função opera em uma cópia dela):

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

Observe que o PHP produz cópias "on-the-fly", ou seja, apenas quando realmente necessário. O end()próprio modifica a matriz, portanto internamente é gerada uma cópia da matriz.


Portanto, a alternativa a seguir é realmente mais rápida, pois internamente não copia a matriz, apenas cria uma fatia:

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

Esse "foreach / return" é um ajuste para obter eficientemente o primeiro (e aqui único) item.


Por fim, a alternativa mais rápida, mas apenas para matrizes indexadas:

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



Para o registro, aqui está outra resposta minha , para o primeiro elemento da matriz.

Gras Double
fonte
você fornece 2 implementações alternativas para uma array_lastfunção. Na primeira, você declara que a $arraycópia é copiada e, na segunda, que não é copiada. Onde está a diferença / por que é copiada na primeira implementação e não na segunda?
Paul van Leeuwen
1
@PaulvanLeeuwen Entendi por que você ficou confuso. Tentei esclarecer a resposta , é melhor?
Gras Double
10

não testado: isso não funcionaria?

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

Como a matriz retornada por array_values ​​é passageira, ninguém liga se o ponteiro é redefinido.

e se você precisar da chave, acho que você faria:

<?php
$last_key=end(array_keys($array));
?>
TecBrat
fonte
9

Preciso disso muitas vezes para lidar com pilhas, e sempre me surpreendo que não haja função nativa que o faça sem manipular a matriz ou seu ponteiro interno de alguma forma.

Então, eu normalmente carrego uma função util que também é segura para uso em matrizes associativas.

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

    $keys = array_keys($array);
    return $array[$keys[sizeof($keys) - 1]];
}
thrau
fonte
1
Boas notícias, eles estão tornando a função nativa :-) Você pode ficar de olho no planejamento de lançamentos aqui: wiki.php.net/todo/php73 (esperado para 13 de dezembro de 2018 no momento em que este artigo foi escrito).
Paul van Leeuwen
9

Para obter o último elemento de uma matriz, use:

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

Referência

Eu iterei 1.000 vezes, capturando o último elemento de matrizes pequenas e grandes que continham 100 e 50.000 elementos, respectivamente.

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

Eu usei a versão 5.5.32 do PHP.

Westy92
fonte
que tal usar $ array [array_keys ($ array) [count (array_keys ($ array)) - 1]]?
user2782001
hmm..array_keys parece ter uma escala muito ruim.
user2782001
1
Na verdade, é muito mais rápido que o grande array (0,0002) apareça o item e coloque-o novamente em ... $ val = $ ar [] = $ array_pop ($ ar);
user2782001
1
@ Westy92 Suas unidades parecem erradas no benchmark. O menor número que você fornece é 0,00031 ... microssegundos, ou seja, cerca de 0,3 nanossegundos. Isso significaria que seu teste demorou um tempo para ser executado se você tiver um computador novo. Suponho que você quis dizer milissegundos ou possivelmente até segundos .
Cesoid
1
Os valores estão claramente errados em várias ordens de magnitude. Por que o foco no desempenho, afinal?
Istepaniuk 16/05/19
6

end () fornecerá o último elemento de uma matriz

$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
fonte
1
Esta solução funciona, mas altera o ponteiro interno da matriz, não acho que seja o caminho certo.
usar o seguinte comando
5

A partir do PHP versão 7.3 as funções array_key_firste array_key_lastfoi introduzido.

Como matrizes no PHP não são tipos de matriz estritos, ou seja, coleções de tamanho fixo de campos de tamanho fixo iniciando no índice 0, mas matriz associativa estendida dinamicamente, o manuseio de posições com chaves desconhecidas é difícil e as soluções alternativas não funcionam muito bem. Por outro lado, matrizes reais seriam endereçadas internamente por aritmética de ponteiros muito rapidamente e o último índice já é conhecido em declaração por tempo de compilação.

Pelo menos o problema com a primeira e a última posição é resolvido pelas funções internas agora desde a versão 7.3. Isso funciona mesmo sem nenhum aviso em literais de matriz fora da caixa:

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

Obviamente, o último valor é:

$array[array_key_last($array)];
Clone de Quasimodo
fonte
1
Obrigado por trazer isso à atenção de todos. Para aqueles que estão ansiosos para usar isso: por favor, não que este seja um RC no momento em que este artigo foi escrito. Está programado para ser lançado em dezembro de 2018.
Paul van Leeuwen
1
Esta é uma grande notícia. Acabei de publicar um polyfill / shim na minha resposta abaixo para que as pessoas possam começar a usar essa sintaxe imediatamente.
Mark Thomson
3
$lastValue = end(array_values($array))

Nenhuma modificação é feita nos ponteiros $ array. Isso evita a

reset($array)

o que pode não ser desejado em determinadas condições.

Vihaan Verma
fonte
3

Para mim:

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

Com associados:

$last =array_values($array)[count($array - 1)]
Mirko Pagliai
fonte
Forneça algum contexto para sua resposta.
Shawn
2
@ Shawn Qual contexto? Não precisa de contexto. Adicionado código para matrizes associativas.
Mirko Pagliai
3

As principais respostas são ótimas, mas como mencionado por @ paul-van-leeuwen e @ quasimodos-clone, o PHP 7.3 apresentará duas novas funções para resolver esse problema diretamente - array_key_first () e array_key_last () .

Você pode começar a usar essa sintaxe hoje mesmo com as seguintes funções de polyfill (ou shim).

// 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)];

Advertência: Isso requer PHP 5.4 ou superior.

Mark Thomson
fonte
2

Para fazer isso e evitar o E_STRICT e não mexer com o ponteiro interno da matriz, você pode usar:

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

$last_element = lelement($array);

O elemento só funciona com uma cópia, para que não afete o ponteiro da matriz.

Damiene
fonte
2

Outra solução:

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

Mais uma solução possível ...

$last_element = array_reverse( $array )[0];
Charles Garrison
fonte
Não trabalhar em matrizes associativas não parece ser motivo suficiente para votar para mim. Em termos de qualidade, essa resposta não é pior do que muitas outras respostas a essa pergunta. Não entendo por que vejo pelo menos 2 votos negativos no momento. (pontuação -2). Enfim, voto positivo para mim, não é tão ruim assim.
Paul van Leeuwen
2

E se:

current(array_slice($array, -1))
  • trabalha para matrizes associativas
  • funciona quando $array == [](retornafalse )
  • não afeta a matriz original
Bouke Versteegh
fonte
2

Você obterá o último elemento de uma matriz facilmente usando a lógica abaixo

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

Não apenas o último elemento, mas você também pode obter o penúltimo, o penúltimo e assim por diante, usando a lógica abaixo.

para o segundo último elemento, você deve passar apenas o número 2 na instrução acima, por exemplo:
echo ($ array [count ($ array) -2]);

Amzad Khan
fonte
1

Para obter o último valor da matriz:

array_slice($arr,-1,1) ;

Para remover a última matriz de formulários de valor:

array_slice($arr,0,count($arr)-1) ;
Rishabh
fonte
1
array_slice($arr,-1,1)resultará em outra matriz com o comprimento 1, não o último elemento
Vic
Vamos dar um exemplo: $a=array("red","green","blue","yellow","brown"); print_r(array_slice($a,-1,1)); Resultado:Array ( [0] => brown )
Rishabh
1

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

Não redefine a matriz e não fornece avisos STRICT.

PS. Como a resposta mais votada ainda não possui parênteses duplos, enviei essa resposta.

Daan
fonte
1

Penso que esta é uma ligeira melhoria em todas as respostas existentes:

$lastElement = count($array) > 0 ? array_values(array_slice($array, -1))[0] : null;
  • Executa melhor que end()ou soluções usandoarray_keys() , especialmente com matrizes grandes
  • Não modifica o ponteiro interno da matriz
  • Não tentará acessar um deslocamento indefinido para matrizes vazias
  • Funcionará como esperado para matrizes vazias, matrizes indexadas, matrizes mistas e matrizes associativas
Adelmar
fonte
Infelizmente, ele não funciona com matrizes associativas, porque o item único da fatia pode ter uma chave nomeada.
Gras Double
Você está certo, editado para adicionar uma correção ( array_valuesna fatia de elemento único)
Adelmar
1

Use a função end ().

$array = [1,2,3,4,5];
$last = end($array); // 5
Brian Berneker
fonte
1
Apenas preste atenção que esta função move o ponteiro do seu array para essa posição.
Giovannipds
Observe também que isso foi postado como resposta há 8 anos. stackoverflow.com/a/3687368/1255289
miken32
1

Hoje em dia, eu preferiria sempre ter esse ajudante, como sugerido na resposta php.net/end .

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

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

Isso sempre mantém o ponteiro como está e nunca teremos que nos preocupar com parênteses, padrões rígidos ou o que for.

giovannipds
fonte
Já mencionado acima: stackoverflow.com/a/45333947/1255289 #
miken32
0

Nota: Para (PHP 7> = 7.3.0) , podemos usar array_key_last - Obtém a última chave de uma matriz

array_key_last ( array $array ) : mixed

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

lokender singh
fonte
1
Isso já foi abordado em várias outras respostas.
miken32
mas eu respondi-lo mais cedo do que outros
lokender singh
-1

E se você quiser obter o último elemento da matriz dentro do loop dela?

O código abaixo resultará em um loop infinito:

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

A solução é obviamente simples para matrizes não associativas:

$last_element = $array[sizeof ($array) - 1];
foreach ($array as $key => $item) {
 if ($last_element == $item) {
   // something useful here
 }
}
Vadim Podlevsky
fonte
2
Eu sei sobre as funções end () e reset (). Meu comentário foi relacionado a loops como foreach ou onde você não pode usar essas funções porque a função reset redefine o ponteiro interno de uma matriz que é usada no loop para iteração. Desculpe por isso, a pergunta era mais simples, eu só queria dar uma situação mais avançada que me deparei no meu projeto. Cumprimentos.
Vadim Podlevsky
Isso está errado de várias maneiras (matrizes com duplicatas, comparação não estrita ...) e, de qualquer forma, não está realmente relacionado à questão.
Tgr
use a função end ($ array) para obter o último elemento, por que você usa loops desnecessariamente?
Mahak Choudhary 15/01/19
1
@MahakChoudhary Meu comentário é um complemento para "como obter o último elemento da matriz, se você já estiver fazendo algumas manipulações dentro de um loop dessa matriz. Usar end () redefinirá o ponteiro innver e interromperá o loop de iteração. Saúde!
Vadim Podlevsky
-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
fonte
-1

A partir do PHP 7.3, array_key_lastestá disponível

$lastEl = $myArray[array_key_last($myArray)];
Tagarikdi Djakouba
fonte
Isso já foi mencionado em várias outras respostas.
miken32
-1

Muito simples

$array = array('a', 'b', 'c', 'd');
end($array)
Jasmeen Maradeeya
fonte
É importante mencionar que isso tem um comportamento estranho se você usar matrizes com intervalos. ou seja $a = array(); $a[2] = 'c'; $a[1] = 'b'; echo end($a); , retornaráb
Simon Zyx 11/10/19
Isso foi publicado há 9 anos atrás. stackoverflow.com/a/3687368/1255289
miken32