es6の配列の最後の要素を取得するための構造化解除


116

coffeescriptではこれは簡単です:

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

es6は同様のことを可能にしますか?

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

もちろん、私はそれをes5の方法で行うことができます-

const a = b[b.length - 1]

しかし、多分これは1つのエラーで少しずれがちです。はじけは、解体の最後にあるだけですか?


7
ES6がすべてを変更し、xyzを実行するための新しい構文があると誰もが思うのはなぜですか?
Felix Kling、2015年

23
@FelixKlingの質問は、特にes6のの動作に関するもの...であり、特に、解体時またはパラメーターリストで最後に使用する場合にのみ使用できます。これは、coffeescriptからes6を使用する人にとって直観に反する可能性があるため、この質問は潜在的に有用です。
George Simms、2015年

それは[1,2,3].slice(-1)あなたに加えてに相当する構造を分解することさえできないことを意味します[1,2,3].slice(0, -1)。これらは一般的な操作です。ES6の解体はなんとなく冗談です!
Scriptum

@正当な理由があります-無限のイテラブルを処理するためです。
George Simms

最初のパラメータが機能しないため、残りが悪すぎます。かっこいいと思います...これはjsperf.com/destructure-last/1のいくつかの回答を使用したjsperf です
Shanimal

回答:


46

ES6 / 2015ではできません。規格はそれを提供していません。

仕様でわかるように、次のFormalParameterListいずれかになります。

  • a FunctionRestParameter
  • a FormalsList(パラメーターのリスト)
  • aのFormalsList後にaFunctionRestParameter

FunctionRestParameterパラメータが続くが提供されていません。


215

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


4
素敵なシンプルな非変異型ソリューション。
ジャックスチーム

1
@Shanimal Depends、私はpopバージョンをできるだけ早く取得しています(OS X、Chrome 68)。
デイブニュートン

1
@Dave Newtonしかしpop()が変異を引き起こす
Antonio Pantano

1
@AntonioPantanoはい、コピーを変更します。ポイントは、それがより高速であるかどうかが与えられたものではないということでした。
デイブニュートン

53

私はES6が少なくともそれを助けることができると信じています:

[...arr].pop()

配列(arr)が未定義ではなく、反復可能な要素(はい、文字列でも機能します!!)がある場合、空の配列でも最後の要素を返す必要があります。空の配列の場合でも、それは変更されません。ただし、中間配列が作成されますが、それほどコストはかかりません。

その場合、例は次のようになります。

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


6
.slice(-1)[0]ええと、それはかなり悪いですが、少しでも悪くはありません、またはvar [last]=arr.slice().reverse()必要であれば別の醜いものです
caub

6
この投稿はES6 / ES2015に関するものだと思いましたが、違いますか?しかし、私は特にあなたの最後の作品が好きです。どのように両者を組み合わせることについて:var [last] = arr.slice(-1);)
shoesel

13
私の好きな方法はObject.defineProperty(Array.prototype, -1, { get() {return this[this.length - 1] } }); [1,2,3][-1]
caub

3
これは機能しますが、変更可能であり、元の配列から項目を削除します。多くのシナリオでは理想的ではありません。
GavKilbride 2017年

4
@GavKilbrideはしません。例は、[].concat(arr).pop();変化しないものと同じarrです。
ダン、

37

逆配列を分解して、必要なものに近づけることができます。

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


2
スマート。より良いですconst last = ['bbb', 'uuu', 'iii'].slice(-1);か?パフォーマンスに関しては?
Vadorequest

1
これ.slice(-1)は技術的には高速ですが、1回の呼び出しで最後の項目とサブ配列の両方が得られないため、構造化...解除時のスプラットの利点になります。長い配列で使用する場合、2回逆転することによるパフォーマンスへの影響を考慮する必要がありますが、小さなスクリプトの場合はおそらく便利でしょうか?しかしlet a = array.slice(-1), rest = array.slice(0,array.length-2)、ES5のワンライナーが必要な場合と同じくらい簡単に、最大4%高速化できます。jsperf.com/last-array-splat
mix3d

17

別のアプローチは:

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


1
@isakbobはい、ここにいます
Den Kerny

読みにくい、またはおそらくそれは私の頭脳にすぎない
webjay

複数の小道具を使用すると非常に役立つので、そう、それはあなただけのものです
。xdxd

5

必ずしも最もパフォーマンスの高い方法とは限りません。しかし、コンテキストに応じて、非常にエレガントな方法は次のようになります。

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

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


3
私は、この溶液中の任意の優雅さを見る、とにかく@shoeselすでにそれを掲載しません
Bergi

2

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

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

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


2
はい、すでに他の解体を行っているときに便利です。単体では、従来のソリューションほど読みやすくありません。
andrhamm

1

これはうまくいくはずです:

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

1

あなたはこのハックを試すことができます:

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

0

間違いなく、問題は破壊についてです JavaScript配列の破棄割り当てを使用して配列の最後の項目を取得することは不可能であることがわかっています。それを不変にする方法があります。以下を参照してください。

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

arr変数は変更しませんが、最後の項目を除くすべての配列メンバーを配列として保持し、最後の項目を個別に持っています。



0

方法を破壊しませんが、助けることができます。JavaScriptのドキュメントと逆の方法によるとこれを試すことができます:

const reversed = array1.reverse();
let last_item = reversed[0]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.