คุณจะจัดเรียงอาร์เรย์โดยไม่ต้องปิดท้ายอาร์เรย์เดิมได้อย่างไร


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

1
@evanmcdonnal สำเนาตื้น ๆ อาจดีพอถ้าต้องการทั้งหมดคือการเรียงลำดับใหม่และไม่ซ้ำกันของทุกรายการในอาร์เรย์
Kekoa

.sortต้องการthisค่าที่จะเป็นอาร์เรย์ดังนั้นสำหรับตัวอย่างข้อมูลสุดท้ายที่จะทำงานคุณจะทำ.sort.call(arr)(แม้ว่ามันจะไม่ได้แก้ปัญหาของคุณ)
pimvdb

@Kekoa ใช่นั่นเป็นจุดที่ดี ไม่จำเป็นที่จะต้องใช้หน่วยความจำมากขึ้นถ้าคุณเพียงแค่เปลี่ยนลำดับขององค์ประกอบและไม่ใช่องค์ประกอบเอง
evanmcdonnal

วิธีการของ zzzzBov ทำงานเหมือนมีเสน่ห์! stackoverflow.com/a/9592774/7011860
Samet 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

3
@ PeterOlson ไม่มันเป็นสำเนาที่ตื้น หากคุณต้องการสำเนาลึก ๆ ให้ใช้คุณลักษณะการค้นหาบน Stack Overflow เพื่อค้นหาคำตอบที่ยอดเยี่ยมที่มีอยู่
Rob W

11
ตอนนี้ Slice มีรายงานว่าเร็วขึ้นอย่างเห็นได้ชัด
ซานเดอร์บราวน์

3
ทำไมArray.prototype.slice.call(arr).sort();แทนarr.slice().sort();?
Olivier Boissé


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

จากนั้นคุณสามารถเรียงลำดับโดยไม่ต้องเปลี่ยนarrCopyarr

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

โปรดทราบ: นี่อาจช้าสำหรับอาร์เรย์ที่มีขนาดใหญ่มาก


สิ่งนี้จะทำงานได้-แทนที่จะเป็น>ตัวอย่างที่สองของคุณ
pootzko

0

ฉันใช้Object.assign ()สำหรับสำเนาส่วนใหญ่ของฉัน:

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

อย่างไรก็ตามหลังจากที่มองผ่านความเห็น OP ที่ฉันวิจัยบิตของการคัดลอกลึกและผลัดกันออก Object.assign ไม่เพียง แต่ดำเนินการสำเนาตื้น แต่ยังเลือกคุณสมบัติเฉพาะนับและตัวเอง (เป็นคำตอบในโพสต์นี้ )

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.