Bagaimana Anda bisa mengurutkan array tanpa mengubah array asli?

230

Anggap saja saya menginginkan fungsi sortir yang mengembalikan salinan array input yang diurutkan. Dengan naif saya mencoba ini

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

dan saya mengujinya dengan ini, yang menunjukkan bahwa sortmetode saya memutasikan array.

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"

Saya juga mencoba pendekatan ini

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

tetapi tidak berhasil sama sekali.

Apakah ada cara langsung di sekitar ini, lebih baik cara yang tidak memerlukan pengguliran tangan algoritma pengurutan saya sendiri atau menyalin setiap elemen dari array ke yang baru?

Peter Olson
sumber
1
buat salinan yang dalam dari array dan sortir saja.
evanmcdonnal
1
@ evanmcdonnal Salinan dangkal mungkin cukup baik jika semua yang diinginkan adalah pemesanan ulang dan bukan duplikat dari setiap item dalam array.
Kekoa
.sortmembutuhkan thisnilai untuk menjadi array, jadi agar potongan terakhir berfungsi, Anda akan melakukannya .sort.call(arr)(meskipun itu tidak menyelesaikan masalah Anda).
pimvdb
@ Kunoa Ya itu poin yang bagus. Tidak perlu mengkonsumsi lebih banyak memori jika Anda hanya akan mengubah urutan elemen dan bukan elemen itu sendiri.
evanmcdonnal
Metode zzzzBov bekerja seperti pesona! stackoverflow.com/a/9592774/7011860
Samet M.

Jawaban:

222

Cukup salin array. Ada banyak cara untuk melakukan itu:

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

// Or:
return Array.prototype.slice.call(arr).sort(); // For array-like objects
Rob W
sumber
2
Apakah ini akan membuat salinan yang dalam, yaitu, apakah objek dan array yang bersarang juga akan disalin?
Peter Olson
2
Apakah ada keuntungan menggunakan concatlebih dari mengatakan slice(0)atau mereka semua hampir sama saja?
JaredPar
3
@PeterOlson Tidak, ini salinan yang dangkal. Jika Anda benar-benar menginginkan salinan yang dalam, gunakan fitur pencarian di Stack Overflow untuk menemukan jawaban yang sangat baik untuk itu.
Rob W
11
Slice sekarang dilaporkan lebih cepat
Zander Brown
3
mengapa Array.prototype.slice.call(arr).sort();bukannya arr.slice().sort();?
Olivier Boissé
61

Coba yang berikut ini

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

The slice(0)ekspresi membuat salinan dari array mulai pukul elemen 0.

JaredPar
sumber
32

Anda bisa menggunakan slice tanpa argumen untuk menyalin array:

var foo,
    bar;
foo = [3,1,2];
bar = foo.slice().sort();
zzzzBov
sumber
Jawaban ini luar biasa! Saya terkejut JavaScript memungkinkan mutasi ke tingkat ini. Tampaknya salah. Terima kasih lagi.
12

Anda juga bisa melakukan ini

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

Dengan cara ini d tidak akan termutasi.

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

//Use it like this
x = [20, 10, 100]
console.log(sorted(x))
Aditya Agarwal
sumber
Jawaban ini bagus
Leasye
1

Siapa pun yang ingin melakukan salinan dalam (mis. Jika array Anda berisi objek) dapat menggunakan:

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

Maka Anda dapat mengurutkan arrCopytanpa mengubah arr.

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

Harap dicatat: ini bisa lambat untuk array yang sangat besar.

Hamada
sumber
Ini akan berfungsi -sebagai gantinya >dalam contoh kedua Anda.
pootzko
0

Saya menggunakan Object.assign () untuk sebagian besar salinan saya:

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

Namun, setelah melihat melalui komentar OP, saya meneliti sedikit penyalinan dalam dan ternyata Object.assign tidak hanya melakukan salinan dangkal, tetapi juga hanya memilih enumerable dan memiliki properti (seperti dijawab dalam posting ini ).

Sun Lee
sumber