Obter o último item em uma matriz

1142

Aqui está o meu código JavaScript até agora:

var linkElement = document.getElementById("BackButton");
var loc_array = document.location.href.split('/');
var newT = document.createTextNode(unescape(capWords(loc_array[loc_array.length-2]))); 
linkElement.appendChild(newT);

Atualmente, leva o penúltimo item da matriz a partir do URL. No entanto, desejo verificar o último item da matriz "index.html"e, em caso afirmativo, pegue o terceiro para o último item.

balexander
fonte

Respostas:

1225
if (loc_array[loc_array.length - 1] === 'index.html') {
   // do something
} else {
   // something else
}

No caso em que o servidor serve a mesma lima para "index.html" e "index.html" você também pode usar: .toLowerCase().

No entanto, você pode considerar fazer isso do lado do servidor, se possível: será mais limpo e funcionará para pessoas sem JS.

Aaron Harun
fonte
1052

Não tenho certeza se há uma desvantagem, mas isso parece bastante conciso:

arr.slice(-1)[0] 

ou

arr.slice(-1).pop()

Ambos retornarão undefinedse a matriz estiver vazia.

kritzikratzi
fonte
32
usar destructuring também é bom:const [lastItem] = arr.slice(-1)
diachedelic 11/11/19
@diachedelic esta é a maneira mais elegante! Impressionante!
Trufa 17/04
2
.pop()remove o último elemento que modifica a matriz original. Não é o mesmo que simplesmente recuperar esse valor.
Badrush
4
O @Badrush slice () cria uma nova matriz com uma cópia de um único elemento e o pop modifica apenas essa cópia. a matriz original permanece ilesa
kritzikratzi
Mas você deve evitar criar novas matrizes, a menos que esse código não seja chamado com frequência. Caso contrário, isso sobrecarregará a coleta de lixo e / ou fará com que o navegador use mais memória.
mvmn 01/06
259

Use Array.pop :

var lastItem = anArray.pop();

Importante : Isso retorna o último elemento e o remove da matriz

mohawke
fonte
165

Uma versão mais curta do que o @chaiguy postou:

Array.prototype.last = function() {
    return this[this.length - 1];
}

A leitura do índice -1 undefinedjá retorna .

EDITAR:

Atualmente, a preferência parece estar usando módulos e evitar tocar no protótipo ou usar um espaço para nome global.

export function last(array) {
    return array[array.length - 1];
}
Aram Kocharyan
fonte
8
Se não é óbvio como isso deve ser realmente usado, aqui está um exemplo: var lastItem = [3,2,1,5].last();. O valor de lastItemé 5.
User128216
7
Esta resposta está correta e também bastante limpa, MAS (!!!) Uma regra prática usando Javascript é essa Do NOT modify objects you Do NOT own. É perigoso por várias razões, como 1. Outros desenvolvedores que trabalham em sua equipe podem ficar confusos, pois esse método não é padrão 2. com qualquer atualização nas bibliotecas ou mesmo usando uma versão ECMAScript mais baixa ou mais alta, ela pode facilmente ser PERDIDA!
Farzad YZ
1
Para quem quer saber, isso quebra Array.forEach (). Eu ainda concordo que modificar protótipos não é a pior coisa que existe, mas este é ruim.
Seph Reed
1
Imo, não há um problema tão grande com a modificação Array.prototype, mas você deve usar Object.assign(Array.prototype, 'last', { value: function () { … } });. Caso contrário, a propriedade será enumerável.
黄雨伞
70

Veja como obtê-lo sem efeito no ARRAY original

a = [1,2,5,6,1,874,98,"abc"];
a.length; //returns 8 elements

Se você usar pop (), ele modificará sua matriz

a.pop();  // will return "abc" AND REMOVES IT from the array 
a.length; // returns 7

Mas você pode usar isso para que não tenha efeito na matriz original:

a.slice(-1).pop(); // will return "abc" won't do modify the array 
                   // because slice creates a new array object 
a.length;          // returns 8; no modification and you've got you last element 
ucefkh
fonte
6
você deve fazer slice (-1) .pop (), caso contrário, você copia toda a matriz (você realmente só precisa copiar o último elemento).
Kritzikratzi 29/05
Não há necessidade de que pop(), em seguida: basta fazêarr.slice(-1)[0]
Christophe Marois
56

A maneira ES6 "mais limpa" (IMO) seria:

const foo = [1,2,3,4];
const bar = [...foo].pop();

Isso evita a mutação foo, como .pop()teria acontecido, se não usássemos o operador de propagação.
Dito isto, eu também gosto da foo.slice(-1)[0]solução.

ddd
fonte
1
Você também pode usar a desestruturação matriz para torná-lo mais ES6;) stackoverflow.com/a/46485581/31671
alex
36
Observe que esta solução executa uma cópia de toda a matriz.
Brendan Annable
4
É tão ilegível quanto .slice(-1)[0]mais lento. Pode bem usar.slice
fregante
12
Copiar toda a matriz apenas para sintaxe "limpa" parece bobagem para mim. Ela não mesmo olhar que Nice
Jemar Jones
43

Eu prefiro usar do array.pop()que índices.

while(loc_array.pop()!= "index.html"){
}
var newT = document.createTextNode(unescape(capWords(loc_array[loc_array.length])));

dessa forma, você sempre obtém o elemento anterior a index.html (desde que sua matriz tenha isolado index.html como um item). Nota: Você perderá os últimos elementos da matriz.

Pablo Mescher
fonte
38

Eu acho que se você quiser apenas pegar o elemento sem remover, é mais simples usar isso:

arr.slice(-1)[0]

Nota: Se a matriz estiver vazia (por exemplo []), isso retornará undefined.

a propósito ... eu não verifiquei o desempenho, mas acho que é mais simples e limpo de escrever

terribleWeb
fonte
Observe que a) isso não retorna o último valor, mas uma matriz com o último elemento ( arr.slice(-1)[0] === arr[arr.length - 1]) eb) é lento porque copia arrpara uma nova matriz (consulte stackoverflow.com/a/51763533/2733244 para obter medições de desempenho).
wortwart
33

const [lastItem] = array.slice(-1);

Array.prototype.slice com -1 pode ser usado para criar uma nova matriz que contém apenas o último item da matriz original. Em seguida, você pode usar a Destructuring Assignment para criar uma variável usando o primeiro item dessa nova matriz.

const lotteryNumbers = [12, 16, 4, 33, 41, 22];
const [lastNumber] = lotteryNumbers.slice(-1);

console.log(lotteryNumbers.slice(-1));
// => [22]
console.log(lastNumber);
// => 22

Jamie Mason
fonte
30

É possível obter o último item de uma matriz usando o método de fatia com valores negativos.

Você pode ler mais sobre isso aqui na parte inferior.

var fileName = loc_array.slice(-1)[0];
if(fileName.toLowerCase() == "index.html")
{
  //your code...
}

Usar pop () mudará sua matriz, o que nem sempre é uma boa ideia.

Mohoch
fonte
1
A fatia retorna uma matriz, portanto arr.slice(-1)[0], use-a como esta resposta .
Cees Timmerman #
4
Se o desempenho for um problema, sei que este método é muito mais lento do que array[array.length - 1] jsperf.com/get-last-item-from-array/13
Bruno Peres
29

Você pode usar esse padrão ...

let [last] = arr.slice(-1);

Embora tenha uma boa leitura, lembre-se de criar uma nova matriz, por isso é menos eficiente do que outras soluções, mas quase nunca será o gargalo de desempenho do seu aplicativo.

alex
fonte
25

Esta questão existe há muito tempo, por isso estou surpreso que ninguém tenha mencionado apenas colocar o último elemento novamente após a pop().

arr.pop()é exatamente tão eficiente quanto arr[arr.length-1], e ambos têm a mesma velocidade que arr.push().

Portanto, você pode se safar com:

--- EDITADO [cheque que thePopnão é undefinedantes de empurrar] ---

let thePop = arr.pop()
thePop && arr.push(thePop)

--- END EDIT ---

O que pode ser reduzido para isso (a mesma velocidade [EDIT: mas insegura!]):

arr.push(thePop = arr.pop())    //Unsafe if arr empty

Isso é duas vezes mais lento que arr[arr.length-1], mas você não precisa mexer em um índice. Isso vale ouro em qualquer dia.

Das soluções que tentei e em múltiplos da Unidade de Tempo de Execução (ETU) de arr[arr.length-1]:

[Método] .............. [ETUs 5 elems] ... [ETU 1 milhão de elems]

arr[arr.length - 1]      ------> 1              -----> 1

let myPop = arr.pop()
arr.push(myPop)          ------> 2              -----> 2

arr.slice(-1).pop()      ------> 36             -----> 924  

arr.slice(-1)[0]         ------> 36             -----> 924  

[...arr].pop()           ------> 120            -----> ~21,000,000 :)

As últimas três opções, ESPECIALMENTE [...arr].pop(), ficam MUITO piores à medida que o tamanho da matriz aumenta. Em uma máquina sem as limitações de memória da minha máquina, [...arr].pop()provavelmente mantém algo como a proporção de 120: 1. Ainda assim, ninguém gosta de recursos.

Paul Parker
fonte
3
Se a matriz inicial puder estar vazia, essa abordagem resultará incorretamente e []será transformada em [undefined]. Você precisa proteger empurrar para trás com explícita undefinedcheque, algo comomyPop !== undefined && arr.push(myPop)
dhilt
23

Se alguém quiser obter o último elemento de uma só vez, ele / ela pode usar Array#splice():

lastElement = document.location.href.split('/').splice(-1,1);

Aqui, não há necessidade de armazenar os elementos divididos em uma matriz e, em seguida, chegar ao último elemento. Se conseguir o último elemento é o único objetivo, isso deve ser usado.

Nota: Isso altera a matriz original removendo seu último elemento. Pense splice(-1,1)como uma pop()função que exibe o último elemento.

user1144616
fonte
5
Isso não retorna o último elemento de uma matriz, em vez do último elemento em si?
2
@tozazaburo não é a mesma coisa?
Aram Kocharyan
5
isso modifica a matriz. você pode usar a fatia (-1) em vez da emenda (-1) para deixar a matriz original intocada. @AramKocharyan não o seu contrário, comparar ["hi"]vs "hi".
Kritzikratzi
20

Para aqueles que não têm medo de sobrecarregar o protótipo Array (e com o mascaramento de enumeração, você não deveria estar):

Object.defineProperty( Array.prototype, "getLast", {
    enumerable: false,
    configurable: false,
    writable: false,
    value: function() {
        return this[ this.length - 1 ];
    }
} );
devios1
fonte
18

O jQuery resolve isso perfeitamente:

> $([1,2,3]).get(-1)
3
> $([]).get(-1)
undefined
Cees Timmerman
fonte
18

Eu geralmente uso underscorejs , com ele você pode fazer

if (_.last(loc_array) === 'index.html'){
  etc...
}

Para mim, isso é mais semântico do que loc_array.slice(-1)[0]

niels
fonte
18

Aqui está mais arte Javascript, se você veio procurá-la

No espírito de outra resposta que usou reduceRight(), mas mais curta:

[3, 2, 1, 5].reduceRight(a => a);

Ele se baseia no fato de que, caso você não forneça um valor inicial, o último elemento será selecionado como o inicial (verifique os documentos aqui ). Como o retorno de chamada continua retornando o valor inicial, o último elemento será o retornado no final.

Lembre-se de que isso deve ser considerado arte Javascript e não é o caminho que eu recomendaria, principalmente porque é executado em O (n) tempo, mas também porque prejudica a legibilidade.

E agora a resposta séria

A melhor maneira que vejo (considerando que você deseja que seja mais conciso do que array[array.length - 1]) é esta:

const last = a => a[a.length - 1];

Então basta usar a função:

last([3, 2, 1, 5])

A função é realmente útil no caso de você estar lidando com uma matriz anônima como a [3, 2, 1, 5]usada acima, caso contrário você teria que instanciar duas vezes, o que seria ineficiente e feio:

[3, 2, 1, 5][[3, 2, 1, 5].length - 1]

Ugh.

Por exemplo, aqui está uma situação em que você tem uma matriz anônima e precisa definir uma variável, mas pode usar last():

last("1.2.3".split("."));
Lucio Paiva
fonte
16

Basta colocar outra opção aqui.

loc_array.splice(-1)[0] === 'index.html'

Achei a abordagem acima mais limpa e curta. Por favor, sinta-se livre para experimentar este.

Nota: Ele modificará a matriz original; se você não quiser modificá-la, poderá usar slice()

loc_array.slice(-1)[0] === 'index.html'

Obrigado @VinayPai por apontar isso.

sidgujrathi
fonte
De acordo com o comentário de stackoverflow.com/users/510036/qix-monica-was-tratou mal neste post stackoverflow.com/questions/9050345/… e os testes em jsperf.com/last-array-element2 que são extremamente lentos
Subash 4/03
13

Várias maneiras de encontrar o último valor de uma matriz em javascript

  • Sem afetar a matriz original

var arr = [1,2,3,4,5];

console.log(arr.slice(-1)[0])
console.log(arr[arr.length-1])
const [last] = [...arr].reverse();
console.log(last)
console.log(arr.reverse()[0])

  • Modifica a matriz original

var arr = [1,2,3,4,5];

console.log(arr.pop())
arr.push(5)
console.log(...arr.splice(-1));

  • Criando o próprio método auxiliar

let arr = [1, 2, 3, 4, 5];

Object.defineProperty(arr, 'last', 
{ get: function(){
  return this[this.length-1];
 }
})

console.log(arr.last);

Vahid Akhtar
fonte
Se o seu primeiro exemplo em que você declara "Sem afetar a matriz original" e fazendo o seguinte: console.log(arr.reverse()[0]) - parabéns, você acabou de modificar a matriz original.
Roko C. Buljan
12
const lastElement = myArray[myArray.length - 1];

Essas são as melhores opções do ponto de vista do desempenho (~ 1000 vezes mais rápido que arr.slice (-1)).

Alexander Burakevych
fonte
10

Pessoalmente, eu gostaria de responder por kuporific / kritzikratzi. O método array [array.length-1] fica muito feio se você estiver trabalhando com matrizes aninhadas.

var array = [[1,2,3], [4,5,6], [7,8,9]]

array.slice(-1)[0]

//instead of 

array[array.length-1]

//Much easier to read with nested arrays

array.slice(-1)[0].slice(-1)[0]

//instead of

array[array.length-1][array[array.length-1].length-1]
Michael Falck Wedelgård
fonte
10

Para impedir a remoção do último item da matriz de origem, você pode usar

Array.from(myArray).pop()

Principalmente suportado por todos os navegadores (ES6)

Alexandr Malinin
fonte
1
boa sorte com grandes matrizes de 100.000 elementos ou mais.
Soldeplata Saketos
9

Você pode adicionar uma last()função ao Arrayprotótipo.

Array.prototype.last = function () {
    return this[this.length - 1];
};
trinalbadger587
fonte
9

O que você fizer, não use apenasreverse() !!!

Algumas respostas mencionam, reversemas não mencionam, o fato de que reversemodifica a matriz original e não (como em outra linguagem ou estrutura) retorna uma cópia.

var animals = ['dog', 'cat'];

animals.reverse()[0]
"cat"

animals.reverse()[0]
"dog"

animals.reverse()[1]
"dog"

animals.reverse()[1]
"cat"

Este pode ser o pior tipo de código para depuração!

Simon_Weaver
fonte
4
Se você deseja uma cópia invertida de sua matriz, pode usar o operador de propagação agora. por exemplo[...animals].reverse()
Josh R
você pode simplesmente copiar a matriz antes de usar reverso[1,3,4,5,"last"].slice().reverse()[0]
Madeo
9

A desestruturação do objeto ES6 é outro caminho a percorrer.

const {length, [length-1]: last}=[1,2,3,4,5]
console.log(last)

Você extrai a propriedade length da matriz usando a destruição do objeto. Você cria outra chave dinâmica usando a chave já extraída por [length-1] e atribui-a ao último , tudo em uma linha.

gautamits
fonte
um pouco complicado, mas inteligente.
Adrien Castagliola 11/03
Obrigado, você pode explicar o que exatamente ele faz?
Tarun Nagpal
8

Você pode adicionar um novo getter de propriedade ao protótipo deArray para que ele seja acessível em todas as instâncias de Array.

Os getters permitem acessar o valor de retorno de uma função como se fosse o valor de uma propriedade. O valor de retorno da função, é claro, é o último valor da matriz ( this[this.length - 1]).

Por fim, envolva-o em uma condição que verifica se a lastpropriedade-ainda está undefined(não definida por outro script que possa confiar nela).

if(typeof Array.prototype.last === 'undefined') {
    Object.defineProperty(Array.prototype, 'last', {
        get : function() {
            return this[this.length - 1];
        }
    });
}

// Now you can access it like
[1, 2, 3].last;            // => 3
// or
var test = [50, 1000];
alert(test.last);          // Says '1000'

Não funciona no IE ≤ 8.

Matmarbon
fonte
Array.prototype.lasté sempre undefined? O if não está funcionando no Chrome 36
bryc
7

EDITADO:

Recentemente, eu vim com mais uma solução que agora acho que é a melhor para minhas necessidades:

function w(anArray) {
  return {
    last() {
      return anArray [anArray.length - 1];
    };
  };
}

Com a definição acima em vigor, agora posso dizer:

let last = w ([1,2,3]).last();
console.log(last) ; // -> 3

O nome "w" significa "invólucro". Você pode ver como você pode facilmente adicionar mais métodos além de 'last ()' a esse wrapper.

Eu digo "melhor para minhas necessidades", porque isso permite que eu adicione facilmente outros "métodos auxiliares" a qualquer tipo interno de JavaScript. O que vem à mente são o carro () e o cdr () do Lisp, por exemplo.

Panu Logic
fonte
Por que usar um invólucro? Se você precisar chamar uma wfunção, faça com que ela retorne o último item.
fregante 19/09/19
w([1,2,3]).lengthestá indefinido. w([1,2,3])[1]está indefinido. Não parece um invólucro para mim. E há um erro de sintaxe. Você tem um ';' extra. Consulte stackoverflow.com/a/49725374/458321 para saber como escrever um wrapper de classe (classe SutString) e usar a reflexão para preencher esse wrapper. Embora, imho, os invólucros sejam um exagero. Melhor usar o encapsulamento, como você quase tem. return { arr: anArray, last() { return anArray[anArray.length - 1]; } };. Além disso, w é muito genérico. A chamada é ArrayW ou algo assim.
TamusJRoyce
6

Eu acho que a maneira mais fácil e super ineficiente é:

var array = ['fenerbahce','arsenal','milan'];
var reversed_array = array.reverse(); //inverts array [milan,arsenal,fenerbahce]
console.log(reversed_array[0]) // result is "milan".
Osman Erdi
fonte
43
Essa solução leva O (n) mais memória e leva O (n) tempo. Realmente não é a solução ideal.
hlin117