Obtenga el último elemento en una matriz

1142

Aquí está mi código JavaScript hasta ahora:

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

Actualmente, toma el penúltimo elemento de la matriz desde la URL. Sin embargo, quiero hacer una comprobación del último elemento de la matriz "index.html"y, de ser así, tomar el tercer al último elemento.

balexander
fuente

Respuestas:

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

En el caso de que el servidor sirve el mismo archivo para "index.html" y "index.html" también se puede utilizar: .toLowerCase().

Sin embargo, es posible que desee considerar hacer este lado del servidor si es posible: será más limpio y funcionará para personas sin JS.

Aaron Harun
fuente
si solo necesitas el último artículo, puedes hacerlo Array.pop ()
Badri Derakhshan hace
1052

No estoy seguro si hay un inconveniente, pero esto parece bastante conciso:

arr.slice(-1)[0] 

o

arr.slice(-1).pop()

Ambos volverán undefinedsi la matriz está vacía.

kritzikratzi
fuente
32
usar la desestructuración también es bueno:const [lastItem] = arr.slice(-1)
diachedelic
@diachedelic esta es la mejor manera! ¡Increíble!
Trufa
2
.pop()elimina el último elemento que modifica la matriz original. No es lo mismo que simplemente recuperar ese valor.
Badrush
44
@Badrush slice () crea una nueva matriz con una copia de un solo elemento, y pop modifica solo esa copia. la matriz original permanece ilesa
kritzikratzi
Pero debe evitar crear nuevas matrices a menos que este código no se llame con frecuencia. De lo contrario, supondrá un esfuerzo adicional para la recolección de basura y / o hará que el navegador use más memoria.
mvmn
259

Utilice Array.pop :

var lastItem = anArray.pop();

Importante : Esto devuelve el último elemento y lo elimina de la matriz.

mohawke
fuente
165

Una versión más corta de lo que publicó @chaiguy:

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

Leer el índice -1 undefinedya regresa .

EDITAR:

En estos días, la preferencia parece ser el uso de módulos y evitar tocar el prototipo o usar un espacio de nombres global.

export function last(array) {
    return array[array.length - 1];
}
Aram Kocharyan
fuente
8
Si no es obvio cómo esto se va a usar en realidad, he aquí un ejemplo: var lastItem = [3,2,1,5].last();. El valor de lastItemes 5.
user128216
77
Esta respuesta es correcta y también bastante limpia PERO (!!!) Una regla general que usa Javascript es esa Do NOT modify objects you Do NOT own. Es peligroso por muchas razones, como 1. Otros desarrolladores que trabajan en su equipo podrían confundirse ya que este método no es estándar 2. Con cualquier actualización en las bibliotecas o incluso utilizando una versión ECMAScript inferior o superior, ¡podría PERDERse fácilmente!
Farzad YZ
1
Para cualquiera que se pregunte, esto rompe Array.forEach (). Todavía estoy de acuerdo en que modificar prototipos no es lo peor, pero este es malo.
Seph Reed
1
Imo, no hay un gran problema con la modificación Array.prototype, pero debes usarlo Object.assign(Array.prototype, 'last', { value: function () { … } });. De lo contrario, la propiedad será enumerable.
雨伞 雨伞
70

Aquí le mostramos cómo obtenerlo sin efecto en el ARRAY original

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

Si usa pop (), modificará su matriz

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

Pero puede usar esto para que no tenga efecto en la 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
fuente
66
debe hacer slice (-1) .pop (), de lo contrario copiará toda la matriz (realmente solo necesita copiar el último elemento).
kritzikratzi
pop()Entonces no hay necesidad de eso : solo hazloarr.slice(-1)[0]
Christophe Marois
56

La forma más limpia de ES6 (IMO) sería:

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

Esto evita la mutación foo, como lo .pop()habría hecho, si no utilizáramos el operador de propagación.
Dicho esto, también me gusta la foo.slice(-1)[0]solución.

ddd
fuente
1
También puede usar la desestructuración de la matriz para hacerlo más ES6;) stackoverflow.com/a/46485581/31671
alex
36
Tenga en cuenta que esta solución realiza una copia de toda la matriz.
Brendan Annable
44
Es tan ilegible como .slice(-1)[0]pero es más lento. También podría usarlo.slice
fregante
12
Copiar toda la matriz solo para una sintaxis "limpia" me parece una tontería. Ni siquiera se ve tan bien
Jemar Jones
43

Prefiero usar array.pop()que los índices.

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

de esta manera siempre obtienes el elemento anterior a index.html (siempre que tu matriz tenga index.html aislado como un elemento). Nota: Sin embargo, perderá los últimos elementos de la matriz.

Pablo Mescher
fuente
38

Creo que si solo quieres obtener el elemento sin eliminar, es más simple usar esto:

arr.slice(-1)[0]

Nota: Si la matriz está vacía (por ejemplo []), esto regresará undefined.

por cierto ... no verifiqué el rendimiento, pero creo que es más simple y limpio de escribir

terribleWeb
fuente
Tenga en cuenta que a) esto no devuelve el último valor, sino una matriz con el último elemento ( arr.slice(-1)[0] === arr[arr.length - 1]), yb) es lento porque se copia arren una nueva matriz (consulte stackoverflow.com/a/51763533/2733244 para medir el rendimiento).
wortwart
33

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

Array.prototype.slice con -1 se puede usar para crear una nueva matriz que contenga solo el último elemento de la matriz original, luego puede usar la asignación de desestructuración para crear una variable usando el primer elemento de esa nueva 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
fuente
30

Se puede obtener el último elemento de una matriz utilizando el método de división con valores negativos.

Puedes leer más sobre esto aquí en la parte inferior.

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

El uso de pop () cambiará su matriz, lo que no siempre es una buena idea.

Mohoch
fuente
1
Sin embargo, Slice devuelve una matriz, así que úsala arr.slice(-1)[0], como esta respuesta .
Cees Timmerman
44
Si el rendimiento es un problema, sepa que este método es mucho más lento que array[array.length - 1] jsperf.com/get-last-item-from-array/13
Bruno Peres
29

Puedes usar este patrón ...

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

Si bien se lee bastante bien, tenga en cuenta que crea una nueva matriz, por lo que es menos eficiente que otras soluciones, pero casi nunca será el cuello de botella de rendimiento de su aplicación.

alex
fuente
25

Esta pregunta ha existido desde hace mucho tiempo, por lo que me sorprende que nadie haya mencionado volver a poner el último elemento después de un pop().

arr.pop()es exactamente tan eficiente como arr[arr.length-1], y ambos tienen la misma velocidad que arr.push().

Por lo tanto, puede salirse con la suya:

--- EDITADO [comprobar que thePopno es undefinedantes de presionar] ---

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

--- EDICIÓN FINAL ---

Que se puede reducir a esto (misma velocidad [EDITAR: ¡pero inseguro!]):

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

Esto es dos veces más lento que arr[arr.length-1], pero no tiene que andar con un índice. Eso vale oro en cualquier día.

De las soluciones que he probado, y en múltiplos de la Unidad de Tiempo de Ejecución (ETU) de arr[arr.length-1]:

[Método] .............. [ETUs 5 elems] ... [ETU 1 millón 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 :)

Las últimas tres opciones, ESPECIALMENTE [...arr].pop(), empeoran MUCHO a medida que aumenta el tamaño de la matriz. En una máquina sin las limitaciones de memoria de mi máquina, [...arr].pop()probablemente mantiene algo así como su relación 120: 1. Aún así, a nadie le gusta un recurso cerdo.

Paul Parker
fuente
3
Si la matriz inicial puede estar vacía, este enfoque resultará incorrectamente y []se convertirá en [undefined]. undefinedmyPop !== undefined && arr.push(myPop)
Debe
23

Si uno quiere obtener el último elemento de una vez, puede usar Array#splice():

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

Aquí, no hay necesidad de almacenar los elementos divididos en una matriz, y luego llegar al último elemento. Si obtener el último elemento es el único objetivo, se debe usar.

Nota: Esto cambia la matriz original al eliminar su último elemento. Piense splice(-1,1)como una pop()función que muestra el último elemento.

usuario1144616
fuente
55
¿No devuelve esto el último elemento en una matriz, en lugar del último elemento en sí?
2
@tozazaburo, ¿no es lo mismo?
Aram Kocharyan
55
Esto modifica la matriz. podría usar la división (-1) en lugar del empalme (-1) para dejar intacta la matriz original. @AramKocharyan no, no, comparar ["hi"]vs "hi".
kritzikratzi
20

Para aquellos que no temen sobrecargar el prototipo de Array (y con el enmascaramiento de enumeración no deberían estarlo):

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

jQuery resuelve esto perfectamente:

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

Generalmente uso subrayado , con él puedes hacer

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

Para mí eso es más semántico que loc_array.slice(-1)[0]

Niels
fuente
18

Aquí hay más arte Javascript si viniste a buscarlo

En el espíritu de otra respuesta que usó reduceRight(), pero más corta:

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

Se basa en el hecho de que, en caso de que no proporcione un valor inicial, el último elemento se selecciona como el inicial (consulte los documentos aquí ). Como la devolución de llamada sigue devolviendo el valor inicial, el último elemento será el que se devuelve al final.

Tenga en cuenta que esto debería considerarse arte Javascript y de ninguna manera recomendaría hacerlo, principalmente porque se ejecuta en tiempo O (n), pero también porque perjudica la legibilidad.

Y ahora por la respuesta seria

La mejor manera que veo (considerando que lo quieres más conciso que array[array.length - 1]) es esto:

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

Entonces solo use la función:

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

La función es realmente útil en caso de que se trate de una matriz anónima como la [3, 2, 1, 5]utilizada anteriormente, de lo contrario, tendría que instanciarla dos veces, lo que sería ineficiente y feo:

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

Ugh

Por ejemplo, aquí hay una situación en la que tiene una matriz anónima y tendría que definir una variable, pero puede usar last()en su lugar:

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

Solo pongo otra opción aquí.

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

Encontré el enfoque anterior más limpio y corto en línea. Por favor, siéntase libre de probar este.

Nota: modificará la matriz original; si no desea modificarla, puede usar slice()

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

Gracias @VinayPai por señalar esto.

sidgujrathi
fuente
Según el comentario de stackoverflow.com/users/510036/qix-monica-was-mistreated en esta publicación stackoverflow.com/questions/9050345/… y las pruebas en jsperf.com/last-array-element2 que es extremadamente lento
Subash
13

Múltiples formas de encontrar el último valor de una matriz en javascript

  • Sin afectar la 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 la matriz original.

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

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

  • Mediante la creación de un método auxiliar propio

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

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

console.log(arr.last);

Vahid Akhtar
fuente
Si su primer ejemplo indica que "Sin afectar la matriz original" y haciendo lo sugerido: console.log(arr.reverse()[0]) - felicidades, acaba de modificar la matriz original.
Roko C. Buljan
12
const lastElement = myArray[myArray.length - 1];

Estas son las mejores opciones desde el punto de vista del rendimiento (~ 1000 veces más rápido que arr.slice (-1)).

Alexander Burakevych
fuente
10

Personalmente, votaría por kuporific / kritzikratzi. El método de matriz [array.length-1] se vuelve muy feo si está trabajando con matrices anidadas.

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
fuente
10

Para evitar eliminar el último elemento de la matriz de origen, puede usar

Array.from(myArray).pop()

Principalmente compatible con todos los navegadores (ES6)

Alexandr Malinin
fuente
1
Buena suerte con grandes matrices de 100.000 elementos o más.
Soldeplata Saketos
9

Puede agregar una last()función al Arrayprototipo.

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

Hagas lo que hagas, ¡no lo uses reverse()!

Algunas respuestas mencionan reversepero no mencionan el hecho de que reversemodifica la matriz original y no devuelve (como en otros lenguajes o marcos) una copia.

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

animals.reverse()[0]
"cat"

animals.reverse()[0]
"dog"

animals.reverse()[1]
"dog"

animals.reverse()[1]
"cat"

¡Este puede ser el peor tipo de código para depurar!

Simon_Weaver
fuente
44
Si desea una copia invertida de su matriz, puede usar el operador de propagación ahora. por ejemplo[...animals].reverse()
Josh R el
simplemente puede copiar la matriz antes de usar el reverso[1,3,4,5,"last"].slice().reverse()[0]
Madeo
9

La desestructuración de objetos ES6 es otro camino a seguir.

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

Extrae la propiedad de longitud de la matriz mediante la desestructuración de objetos. Puede crear otra clave dinámica utilizando la clave ya extraída por [longitud-1] y asignarla al último , todo en una línea.

gautamits
fuente
un poco complicado pero inteligente.
Adrien Castagliola
Gracias, ¿puedes explicar qué hace exactamente?
Tarun Nagpal
8

Puede agregar un nuevo captador de propiedades al prototipo deArray modo que sea accesible a través de todas las instancias de Array.

Los captadores le permiten acceder al valor de retorno de una función como si fuera el valor de una propiedad. El valor de retorno de la función, por supuesto, es el último valor de la matriz ( this[this.length - 1]).

Finalmente lo envuelve en una condición que verifica si la lastpropiedad todavía está undefined(no definida por otro script que pueda depender de ella).

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'

No funciona en IE ≤ 8.

Matmarbon
fuente
Array.prototype.lastes siempre undefined? El if no funciona en Chrome 36
bryc
7

EDITADO:

Recientemente se me ocurrió una solución más que ahora creo que es la mejor para mis necesidades:

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

Con la definición anterior en efecto, ahora puedo decir:

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

El nombre "w" significa "envoltorio". Puede ver cómo podría agregar fácilmente más métodos además de 'last ()' a este contenedor.

Digo "lo mejor para mis necesidades", porque esto me permite agregar fácilmente otros "métodos auxiliares" a cualquier tipo de JavaScript incorporado. Lo que viene a la mente son el auto () y el cdr () de Lisp, por ejemplo.

Panu Logic
fuente
¿Por qué usar una envoltura? Si tiene que llamar a una wfunción, simplemente haga que la función devuelva el último elemento.
fregante
w([1,2,3]).lengthes indefinido. w([1,2,3])[1]es indefinido. No me parece una envoltura. Y hay un error de sintaxis. Tienes un ';' extra. Consulte stackoverflow.com/a/49725374/458321 para saber cómo escribir un contenedor de clase (clase SutString) y usar la reflexión para llenar ese contenedor. Aunque, en mi humilde opinión, los envoltorios son excesivos. Es mejor usar encapsulación, como casi lo tienes. return { arr: anArray, last() { return anArray[anArray.length - 1]; } };. Además, w es demasiado genérico. La llamada es ArrayW o algo así.
TamusJRoyce
6

Creo que la forma más fácil y súper ineficiente es:

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
fuente
43
Esta solución toma O (n) más memoria y toma O (n) tiempo. Realmente no es la solución ideal.
hlin117