元の配列を変更せずにJavaScriptで配列を反転


190

Array.prototype.reverse 配列の内容を所定の位置に反転します(変更あり)...

元の配列の内容を変更せずに(突然変異なしで)配列を逆にするための同様に単純な戦略はありますか?



さまざまなオプションを比較するベンチマークは次のとおり
ソロモンUcko

回答:


377

あなたはslice()を使用してコピーを作成し、それをreverse()することができます

var newarray = array.slice().reverse();


パラメータなしでslice()を説明できますか?
Alex

3
@Alex スライス -- If begin is omitted, slice begins from index 0.だから同じarray.slice(0)
アルンPジョニー

2
@アレックスは「あなたの答えでそれを説明する」という意味だと思います...関係なく...素晴らしい解決策。ありがとう!
sfletche 2015年

13
これは非常に誤解を招く方法であるため、この方法の使用はお勧めしません。slice()を使用していて、実際には何もスライスしていないと、非常に混乱します。不変の反転が必要な場合は、新しいコピーを作成してください: const newArray = [... array] .reverse()
Oleg Matei

105

ES6の場合:

const newArray = [...array].reverse()

2
これのパフォーマンスは、受け入れられた回答のパフォーマンスとどのように比較されますか?彼らは同じですか?
ケイティ

@Katie非常に似ており、どちらも非常に高速で、Chrome [...].reverseは非常に単純なテストケースで優位に立つように見えます。jsperf.com/reverse-vs-slice-reverse/1
ブライアンM.ハント

4
一貫して.slice大幅に高速化しています。
James Coyle

3
@JamesCoyleおそらくブラウザとOSに依存sliceしますが、高速になる可能性がありますb / c [...]は配列への反復可能な汎用であるため、それほど多くの仮定を行うことはできません。またslice、長い間使用されてきたb / cがより最適化されている可能性があります。
ブライアンM.ハント

私の考えは正確です。
James Coyle

11

別のES6バリアント:

を使用.reduceRight()して、実際に反転させずに反転配列を作成することもできます。

let A = ['a', 'b', 'c', 'd', 'e', 'f'];

let B = A.reduceRight((a, c) => (a.push(c), a), []);

console.log(B);

役立つリソース:


2
reduceRightis slow af
ドラゴスリゼスク2018年

@DragosRizescuサンプルのテスト結果を共有できますか?
Mohammad Usman

1
これがあなたが遊ぶことができるリポジトリです:(最良の例ではありませんが、Reactコンテキストで誰かとこの議論があったので、私はそれをまとめました):github.com/rizedr/reduce-vs-reduceRight
Dragos Rizescu 2018年

4
(a, c) => a.concat([c])より慣用的な感じ(a, c) => (a.push(c), a)
カイル・リン

1
@DragosRizescuそれは実際にこれが3つのトップアンサーの中で最速であるように見えます。jsperf.com/reverse-vs-slice-reverse/3
DBosley

7

この再帰的な解決策を試してください:

const reverse = ([head, ...tail]) => 
    tail.length === 0
        ? [head]                       // Base case -- cannot reverse a single element.
        : [...reverse(tail), head]     // Recursive case

reverse([1]);               // [1]
reverse([1,2,3]);           // [3,2,1]
reverse('hello').join('');  // 'olleh' -- Strings too!                              

1
これは、空の配列で壊れるように見えます。
Matthias

6

ES6の代替として使用.reduce()および拡散。

const foo = [1, 2, 3, 4];
const bar = foo.reduce((acc, b) => ([b, ...acc]), []);

基本的には、fooの次の要素で新しい配列を作成し、bの後に反復ごとに累積された配列を分散します。

[]
[1] => [1]
[2, ...[1]] => [2, 1]
[3, ...[2, 1]] => [3, 2, 1]
[4, ...[3, 2, 1]] => [4, 3, 2, 1]

あるいは.reduceRight()、上記のように、ただし.push()突然変異はありません。

const baz = foo.reduceRight((acc, b) => ([...acc, b]), []);

4

変更せずに配列を逆にする方法は複数あります。それらの2つは

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

// Using Splice
var reverseArray1 = array.splice().reverse(); // Fastest

// Using spread operator
var reverseArray2 = [...array].reverse();

// Using for loop 
var reverseArray3 = []; 
for(var i = array.length-1; i>=0; i--) {
  reverseArray.push(array[i]);
}

パフォーマンステストhttp://jsben.ch/guftu


0

INTOプレーンJavascript:

function reverseArray(arr, num) {
  var newArray = [];
  for (let i = num; i <= arr.length - 1; i++) {
    newArray.push(arr[i]);
  }

  return newArray;
}

0

説明のためだけに変数を入れ替えて元に戻す(ただし、変更したくない場合はコピーが必要)

const myArr = ["a", "b", "c", "d"];
const copy = [...myArr];
for (let i = 0; i < (copy.length - 1) / 2; i++) {  
    const lastIndex = copy.length - 1 - i; 
    [copy[i], copy[lastIndex]] = [copy[lastIndex], copy[i]] 
}

-4

es6:

const reverseArr = [1,2,3,4].sort(()=>1)

4
ラジオンへようこそ!回答を残すときは、通常、回答が機能する理由と、この結論に達した理由を説明することをお勧めします。これは、新しいユーザーが指定した対話と言語を理解するのに役立ちます。
イーサンフィールド

Radionの防御1では、Array.prototype.sortコールバック(またはいわゆるcompare function)が動作する方法であるため、最後にゼロより大きいものになる可能性があります。それは常に最初のものの前で二番目の数字に移動すると言うので、基本的には、常にこのような場合には常に正比較リターンを2つの数字を比較して:)これはとても説明です: stackoverflow.com/questions/6567941/...
iulial

8
sort()配列を変更します(つまり、その場所で並べ替えます)。これは、OPが避けたいものです。
クリントハリス

5
この答えはいくつかの点で間違っています。(1)@ClintHarrisが指摘するように、配列を変更するため、.reverse()に勝るものはありません。(2)コンパレータは不正です。a、bに1を返す場合、b、aに負の数を返す必要があります。あなたの答えがいくつかの実装で配列を逆にする場合、それは完全に運によるものです。
ドンハッチ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.