Destructuring to get the last element of an array in es6

Ecmascript 6Destructuring

Ecmascript 6 Problem Overview


In coffeescript this is straightforward:

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

Does es6 allow for something similar?

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

Of course I can do it the es5 way -

const a = b[b.length - 1]

But maybe this is a bit prone to off by one errors. Can the splat only be the last thing in the destructuring?

Ecmascript 6 Solutions


Solution 1 - Ecmascript 6

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

Solution 2 - Ecmascript 6

I believe ES6 could at least help with that:

[...arr].pop()

Given your array (arr) is not undefined and an iterable element (yes, even strings work!!), it should return the last element..even for the empty array and it doesn't alter it either. It creates an intermediate array though..but that should not cost much.

Your example would then look like this:

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

Solution 3 - Ecmascript 6

It is not possible in ES6/2015. The standard just doesn't provide for it.

As you can see in the spec, the FormalParameterList can either be:

  • a FunctionRestParameter
  • a FormalsList (a list of parametes)
  • a FormalsList, followed by a FunctionRestParameter

Having FunctionRestParameter followed by parameters is not provided.

Solution 4 - Ecmascript 6

You can destructure the reversed array to get close to what you want.

const [a, ...rest] = ['a', 'b', 'program'].reverse();

document.body.innerHTML = 
    "<pre>"
    + "a: " + JSON.stringify(a) + "\n\n"
    + "rest: " + JSON.stringify(rest.reverse())
    + "</pre>";

Solution 5 - Ecmascript 6

another approach is:

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

Solution 6 - Ecmascript 6

Not necessarily the most performant way of doing. But depending on the context a quite elegant way would be:

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

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

Solution 7 - Ecmascript 6

Getting the last element of the array:

const [last,] = ['a', 'b', 'program'].reverse();

Solution 8 - Ecmascript 6

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

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

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

Solution 9 - Ecmascript 6

This should work:

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

Solution 10 - Ecmascript 6

Not destructing way but could help. According to javascript documentation and reverse method could be try this:

const reversed = array1.reverse();
let last_item = reversed[0]

Solution 11 - Ecmascript 6

You could further destruct array´s ...rest array as Object, in order to get its length prop and build a computed prop name for the last index.

This even works for parameter destruction:

const a = [1, 2, 3, 4];

// Destruct from array ---------------------------
const [A_first, ...{length: l, [l - 1]: A_Last}] = a;
console.log('A: first: %o; last: %o', A_first, A_Last);     // A: first: 1; last: 4

// Destruct from fn param(s) ---------------------
const fn = ([B_first, ...{length: l, [l - 1]: B_Last}]) => {
  console.log('B: first: %o; last: %o', B_first, B_Last);   // B: first: 1; last: 4
};

fn(a);

Solution 12 - Ecmascript 6

You can try using object destructuring applied to an array to extract the length and then get last item: e.g.:

const { length, 0: first, [length - 1]: last } = ['a', 'b', 'c', 'd']

// length = 4
// first = 'a'
// last = 'd'

UPDATE

Another approach Array.prototype.at()

> The at() method takes an integer value and returns the item at that index, allowing for positive and negative integers...

const last = ['a', 'b', 'c', 'd'].at(-1)
// 'd'

Solution 13 - Ecmascript 6

let a = [1,2,3]
let [b] = [...a].reverse()

Solution 14 - Ecmascript 6

You can try this hack:

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

Solution 15 - Ecmascript 6

Definitely, the question is about Destructuring for JavaScript Arrays, and we know it is not possible to have the last item of an Array by using the destructuring assignment, there is a way to do it immutable, see the following:

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

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

const allExceptTheLast = arr.filter( (_, index) => index !== arrLength );
const [ theLastItem ] = arr.filter( (_, index) => index === arrLength );

We do not mutate the arr variable but still have all the array members except the last item as an array and have the last item separately.

Solution 16 - Ecmascript 6

Using array deconstructing: "capturing" the array, "spliced" array (arrMinusEnd), and "poped"/"sliced" element (endItem).

var [array, arrMinusEnd, endItem] = 
  ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"]
  .reduce(
    (acc, cv, idx, arr) => {
      if(idx<arr.length-1) acc[1].push(cv);
      else {
        acc[0]=arr;
        acc[2]=cv;
      };
      return acc;
    },
    [null,[],[]]
  )
;

console.log("array=");
console.log(array);
console.log("arrMinusEnd=");
console.log(arrMinusEnd);
console.log("endItem=\""+endItem+"\"");

.as-console-wrapper { max-height: 100% !important; top: 0; }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGeorge SimmsView Question on Stackoverflow
Solution 1 - Ecmascript 6Ryan HuangView Answer on Stackoverflow
Solution 2 - Ecmascript 6shoeselView Answer on Stackoverflow
Solution 3 - Ecmascript 6Andrey Mikhaylov - lolmausView Answer on Stackoverflow
Solution 4 - Ecmascript 6Jeff HortonView Answer on Stackoverflow
Solution 5 - Ecmascript 6Den KernyView Answer on Stackoverflow
Solution 6 - Ecmascript 6theTaoOfJSView Answer on Stackoverflow
Solution 7 - Ecmascript 6Chinmoy AcharjeeView Answer on Stackoverflow
Solution 8 - Ecmascript 6andrhammView Answer on Stackoverflow
Solution 9 - Ecmascript 6OPulidoView Answer on Stackoverflow
Solution 10 - Ecmascript 6Pamela HdzView Answer on Stackoverflow
Solution 11 - Ecmascript 6Exodus 4DView Answer on Stackoverflow
Solution 12 - Ecmascript 6SerchstackView Answer on Stackoverflow
Solution 13 - Ecmascript 6Andrew NekowitschView Answer on Stackoverflow
Solution 14 - Ecmascript 6Ups BazaarView Answer on Stackoverflow
Solution 15 - Ecmascript 6AmerllicAView Answer on Stackoverflow
Solution 16 - Ecmascript 6iAmOrenView Answer on Stackoverflow