Destrutturazione per ottenere l'ultimo elemento di un array in es6


116

In coffeescript questo è semplice:

coffee> a = ['a', 'b', 'program']
[ 'a', 'b', 'program' ]
coffee> [_..., b] = a
[ 'a', 'b', 'program' ]
coffee> b
'program'

Es6 consente qualcosa di simile?

> const [, b] = [1, 2, 3]                              
'use strict'                                           
> b  // it got the second element, not the last one!                      
2                                                      
> const [...butLast, last] = [1, 2, 3]          
SyntaxError: repl: Unexpected token (1:17)                                                                                                                                                        
> 1 | const [...butLast, last] = [1, 2, 3]                                                                                                                                                        
    |                  ^                                                                                                                                                                          
    at Parser.pp.raise (C:\Users\user\AppData\Roaming\npm\node_modules\babel\node_modules\babel-core\node_modules\babylon\lib\parser\location.js:24:13)                                           

Certo che posso farlo nel modo es5 -

const a = b[b.length - 1]

Ma forse questo è un po 'soggetto a errori. Lo splat può essere solo l'ultima cosa nella destrutturazione?


7
Perché tutti pensano che ES6 cambi tutto e che ci sia una nuova sintassi per fare xyz?
Felix Kling

23
@FelixKling la domanda riguarda in particolare il comportamento di ...in es6, in particolare che può essere utilizzato solo come ultima cosa durante la destrutturazione o in un elenco di parametri. Questo è potenzialmente controintuitivo per qualcuno che entra in es6 da coffeescript e quindi questa domanda è potenzialmente utile.
George Simms

Ciò significa che inoltre [1,2,3].slice(-1)non puoi nemmeno destrutturare l'equivalente di [1,2,3].slice(0, -1). Queste sono operazioni comuni. La destrutturazione di ES6 è in qualche modo uno scherzo!
scriptum

@ Anche se c'è una ragione legittima: gestire infiniti iterabili.
George Simms

Peccato riposare perché il primo parametro non funziona. Sarebbe stato bello ... Ecco un jsperf che usa alcune delle risposte jsperf.com/destructure-last/1
Shanimal

Risposte:


46

Non è possibile in ES6 / 2015. Lo standard semplicemente non lo prevede.

Come puoi vedere nelle specifiche , FormalParameterListpuò essere:

  • un' FunctionRestParameter
  • a FormalsList(un elenco di parametri)
  • a FormalsList, seguito da aFunctionRestParameter

L'avere FunctionRestParameterseguito da parametri non è fornito.


215

console.log('last', [1, 3, 4, 5].slice(-1));
console.log('second_to_last', [1, 3, 4, 5].slice(-2));


4
Bella semplice soluzione non mutativa.
Jack Steam

1
@Shanimal Depends, sto ottenendo la popversione più veloce (OS X, Chrome 68).
Dave Newton

1
@Dave Newton Ma pop () causa mutazione
Antonio Pantano

1
@AntonioPantano Sì, muta la copia. Il punto era se fosse o meno più veloce non è scontato.
Dave Newton

53

Credo che ES6 possa almeno aiutare con questo:

[...arr].pop()

Dato che il tuo array (arr) non è indefinito e un elemento iterabile (sì, anche le stringhe funzionano !!), dovrebbe restituire l'ultimo elemento .. anche per l'array vuoto e non lo altera neanche. Tuttavia crea un array intermedio ... ma non dovrebbe costare molto.

Il tuo esempio sarebbe quindi simile a questo:

  console.log(  [...['a', 'b', 'program']].pop() );


6
uhh, è piuttosto brutto, anche .slice(-1)[0]leggermente meno cattivo, o var [last]=arr.slice().reverse()è un altro brutto se ne hai bisogno
caub

6
Pensavo che questo post riguardasse ES6 / ES2015, no? Ma mi piace soprattutto il tuo ultimo pezzo. Che ne dici di combinare i due var [last] = arr.slice(-1)
:;

13
il mio modo preferito èObject.defineProperty(Array.prototype, -1, { get() {return this[this.length - 1] } }); [1,2,3][-1]
caub

3
Sebbene funzioni, è mutativo e rimuove l'elemento dall'array originale. Non è l'ideale in molti scenari.
GavKilbride

4
@GavKilbride non lo fa. L'esempio è lo stesso [].concat(arr).pop();che non muta arr.
Dan

37

Puoi destrutturare l'array invertito per avvicinarti a ciò che desideri.

const [a, ...rest] = ['a', 'b', 'program'].reverse();
  
document.body.innerHTML = 
    "<pre>"
    + "a: " + JSON.stringify(a) + "\n\n"
    + "rest: " + JSON.stringify(rest.reverse())
    + "</pre>";


2
Inteligente. Meglio di const last = ['bbb', 'uuu', 'iii'].slice(-1);? In termini di prestazioni?
Vadorequest

1
l' .slice(-1)è tecnicamente più veloce, ma non ti dà sia l'ultimo elemento E il sottoarray in una chiamata, che è un vantaggio del ...splat quando destrutturazione. Il successo delle prestazioni dell'inversione due volte deve essere considerato quando viene utilizzato su array più lunghi, ma per un piccolo script probabilmente vale la pena? Ma potresti altrettanto facilmente let a = array.slice(-1), rest = array.slice(0,array.length-2)se volessi ancora l'oneliner in ES5, che è ~ 4% più veloce. jsperf.com/last-array-splat
mix3d

17

un altro approccio è:

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


1
@isakbob yeap, eccoti qui
Den Kerny

difficile da leggere, o forse è solo il mio cervello
webjay

potrebbe essere molto utile usare più oggetti di scena, quindi sì, è solo tuo, xd xd xd
Den Kerny

5

Non necessariamente il modo più performante di fare. Ma a seconda del contesto un modo abbastanza elegante sarebbe:

const myArray = ['one', 'two', 'three'];
const theOneIWant = [...myArray].pop();

console.log(theOneIWant); // 'three'
console.log(myArray.length); //3


3
Non vedo eleganza in questa soluzione, ma comunque @shoesel l'ha già postata
Bergi

2

const arr = ['a', 'b', 'c']; // => [ 'a', 'b', 'c' ]

const {
  [arr.length - 1]: last
} = arr;

console.log(last); // => 'c'


2
Sì, lo trovo utile quando si stanno già facendo altre destrutturazioni. Di per sé non è così facile da leggere come la soluzione classica.
andrhamm

1

Questo dovrebbe funzionare:

const [lastone] = myArray.slice(-1);

1

Puoi provare questo trucco:

let a = ['a', 'b', 'program'];
let [last] = a.reverse();
a.reverse();
console.log(last);

0

Sicuramente, la domanda riguarda la destrutturazione per array JavaScript e sappiamo che non è possibile avere l'ultimo elemento di un array utilizzando l'assegnazione destrutturante, c'è un modo per farlo immutabile , vedere quanto segue:

const arr = ['a', 'b', 'c', 'last'];

~~~
const arrDepth = arr.length - 1;

const allExceptTheLast = arr.filter( (dep, index) => index !== arrDepth && dep );
const [ theLastItem ] = arr.filter( (dep, index) => index === arrDepth && dep );

Non mutiamo la arrvariabile ma abbiamo ancora tutti i membri dell'array tranne l'ultimo elemento come array e abbiamo l'ultimo elemento separatamente.



0

Non distrugge il modo ma potrebbe aiutare. Secondo la documentazione javascript e il metodo inverso potrebbe essere provato questo:

const reversed = array1.reverse();
let last_item = reversed[0]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.