元の配列を変更せずに配列を並べ替えるにはどうすればよいですか?


230

入力された配列のソートされたコピーを返すソート関数が必要だとしましょう。私は単純にこれを試しました

function sort(arr) {
  return arr.sort();
}

私はこれをテストしました。これは、私のsortメソッドが配列を変更していることを示しています。

var a = [2,3,7,5,3,7,1,3,4];
sort(a);
alert(a);  //alerts "1,2,3,3,3,4,5,7,7"

私もこのアプローチを試しました

function sort(arr) {
  return Array.prototype.sort(arr);
}

しかし、それはまったく機能しません。

これを回避する簡単な方法はありますか?できれば、自分の並べ替えアルゴリズムを手動でローリングしたり、配列のすべての要素を新しい要素にコピーしたりする必要がない方法が望ましいでしょうか?


1
配列のディープコピーを作成し、代わりに並べ替えます。
evanmcdonnal 2012年

1
@evanmcdonnal配列内のすべての項目の複製ではなく、並べ替えだけが必要な場合は、浅いコピーで十分な場合があります。
Kekoa、2012年

.sortthis値は配列である必要があるため、最後のスニペットが機能する.sort.call(arr)ためには、問題は解決しませんが、
pimvdb

@Kekoaそうですね。要素自体ではなく要素の順序を変更するだけの場合は、より多くのメモリを消費する必要はありません。
evanmcdonnal

zzzzBovの方法は魅力のように働いています!stackoverflow.com/a/9592774/7011860
サメットM.

回答:


222

アレイをコピーするだけです。それには多くの方法があります。

function sort(arr) {
  return arr.concat().sort();
}

// Or:
return Array.prototype.slice.call(arr).sort(); // For array-like objects

2
これはディープコピーを実行しますか?つまり、ネストされたオブジェクトと配列もコピーされますか?
Peter Olson、

2
concat言う以上に利点はありますslice(0)か、それともまったく同じですか?
JaredPar 2012年

3
@PeterOlsonいいえ、それは浅いコピーです。ディープコピーが本当に必要な場合は、Stack Overflowの検索機能を使用して、既存の優れた回答を見つけてください。
Rob W

11
スライスは現在、著しく高速であると報告されています
Zander Brown

3
なぜArray.prototype.slice.call(arr).sort();代わりにarr.slice().sort();
OlivierBoissé19年


61

以下をお試しください

function sortCopy(arr) { 
  return arr.slice(0).sort();
}

slice(0)発現は、要素0でアレイ開始のコピーを作成します。


32

引数なしでスライスを使用して配列をコピーできます。

var foo,
    bar;
foo = [3,1,2];
bar = foo.slice().sort();

この答えは素晴らしいです!JavaScriptがこの程度の変更を許可することに驚いています。間違っているようです。再度、感謝します。

12

これもできます

d = [20, 30, 10]
e = Array.from(d)
e.sort()

この方法では、dは変化しません。

function sorted(arr) {
  temp = Array.from(arr)
  return temp.sort()
}

//Use it like this
x = [20, 10, 100]
console.log(sorted(x))

この答えはいいです
Leasye

1

ディープコピーをしたい人は(たとえば、配列にオブジェクトが含まれている場合)、以下を使用できます。

let arrCopy = JSON.parse(JSON.stringify(arr))

その後、arrCopy変更せずに並べ替えることができますarr

arrCopy.sort((obj1, obj2) => obj1.id > obj2.id)

注意:非常に大きな配列の場合、これは遅くなる可能性があります。


これは、2番目の例の-代わりに機能>します。
pootzko

0

ほとんどのコピーにObject.assign()を使用しています。

var copyArray = Object.assign([], originalArray).sort();

しかし、OPのコメントを調べた後、私は少し深いコピーを調査したところ、Object.assignは浅いコピーを実行するだけでなく、列挙可能な独自のプロパティのみを選択していることがわかりました(この投稿で回答)。

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