ย้อนกลับอาร์เรย์ใน Javascript โดยไม่ต้องปิดท้ายอาร์เรย์เดิม


190

Array.prototype.reverse ย้อนกลับเนื้อหาของอาร์เรย์ในสถานที่ (กับการกลายพันธุ์) ...

มีกลยุทธ์อย่างง่าย ๆ ที่คล้ายกันสำหรับการย้อนกลับอาร์เรย์โดยไม่มีการเปลี่ยนแปลงเนื้อหาของอาร์เรย์เดิม (โดยไม่มีการเปลี่ยนแปลง) หรือไม่?



นี่คือมาตรฐานเปรียบเทียบตัวเลือกต่าง ๆ : jsben.ch/HZ7Zp
โซโลมอน Ucko

คำตอบ:


378

คุณสามารถใช้slice ()เพื่อทำสำเนาจากนั้นย้อนกลับ ()ได้

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


คุณช่วยอธิบายชิ้น () โดยไม่มีพารามิเตอร์ได้ไหม
Alex

3
@Alex slice - If begin is omitted, slice begins from index 0.- ดังนั้นจึงเป็นเช่นเดียวกับarray.slice(0)
Arun P Johny

2
ฉันคิดว่า @Alex หมายถึง 'อธิบายในคำตอบของคุณ' ... โดยไม่คำนึงถึง ... ทางออกที่ยอดเยี่ยม ขอบคุณ!
sfletche

15
ฉันจะไม่แนะนำให้ใช้วิธีนี้เพราะเป็นการฝึกฝนที่ทำให้เข้าใจผิดมาก มันสับสนมากเมื่อคุณใช้ slice () และคุณไม่ได้หั่นอะไรเลย หากคุณต้องการย้อนกลับไม่เปลี่ยนรูปเพียงแค่สร้างสำเนาใหม่ใหม่: const newArray = [... array] .reverse ()
Oleg Matei

106

ใน ES6:

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

2
ประสิทธิภาพของสิ่งนี้เปรียบเทียบกับคำตอบที่ยอมรับได้อย่างไร พวกเขาเหมือนกันหรือไม่
Katie

@ Katie คล้ายกันมากทั้งสองอย่างรวดเร็วโดย Chrome ดูเหมือนจะให้[...].reverseขอบในกรณีทดสอบที่ง่ายมาก jsperf.com/reverse-vs-slice-reverse/1
Brian M. Hunt

4
ฉันได้รับ.sliceเร็วขึ้นอย่างต่อเนื่องอย่างมีนัยสำคัญ
James Coyle

3
@JamesCoyle อาจเป็นไปได้ว่าเบราว์เซอร์และระบบปฏิบัติการขึ้นอยู่กับการใช้งาน แต่sliceมีแนวโน้มที่จะเร็วขึ้น b / c [...]เป็น iterable-to-array ทั่วไปดังนั้นจึงไม่สามารถตั้งสมมติฐานได้มากนัก รวมถึงมีแนวโน้มที่sliceจะเพิ่มประสิทธิภาพ b / c ที่ดีขึ้นมาเป็นเวลานาน
Brian M. Hunt

ความคิดของฉันอย่างแน่นอน
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
reduceRightช้ามาก
Dragos Rizescu

@DragosRizescu คุณสามารถแบ่งปันผลการทดสอบตัวอย่างได้ไหม?
Mohammad Usman

1
นี่คือ repo ที่คุณสามารถเล่นกับ: (ไม่ใช่ตัวอย่างที่ดีที่สุด แต่มีข้อโต้แย้งกับใครบางคนในขณะที่ผ่านมาในบริบทของ React ดังนั้นฉันจึงรวมมันไว้ด้วยกัน): github.com/rizedr/reduce-vs-reduceRight
Dragos Rizescu

4
(a, c) => a.concat([c])รู้สึกสำนวนมากกว่า(a, c) => (a.push(c), a)
Kyle Lin

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

มีหลายวิธีในการย้อนกลับอาร์เรย์โดยไม่ต้องแก้ไข สองของพวกเขาคือ

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

จาวาสคริปต์ธรรมดาใน:

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
ยินดีต้อนรับสู่ SO, Radion! เมื่อออกจากคำตอบโดยทั่วไปแล้วเป็นความคิดที่ดีที่จะอธิบายว่าทำไมคำตอบของคุณถึงใช้ได้และทำไมคุณถึงได้ข้อสรุปนี้สิ่งนี้จะช่วยให้ผู้ใช้รายใหม่เข้าใจการโต้ตอบและภาษาที่คุณระบุ
Ethan Field

ในการป้องกันของ Radion: P ว่า1ท้ายที่สุดอาจเป็นอะไรที่มากกว่าศูนย์เพราะนั่นเป็นวิธีการArray.prototype.sortโทรกลับ (หรือเรียกอีกอย่างหนึ่งcompare function) โดยทั่วไปคุณจะเปรียบเทียบตัวเลข 2 ตัวเสมอและในกรณีนี้การเปรียบเทียบจะส่งกลับค่าเป็นบวกเสมอดังนั้นจึงบอกว่าให้ย้ายไปยังหมายเลขที่สองที่อยู่ด้านหน้าของหมายเลขแรกเสมอ :) นี่เป็นคำอธิบายที่ดีมาก: stackoverflow.com/questions/6567941/ …
iulial

8
sort()กลายพันธุ์อาร์เรย์ (เช่นเรียงลำดับในสถานที่) ซึ่งเป็นสิ่งที่ OP ต้องการหลีกเลี่ยง
Clint Harris

5
คำตอบนี้ผิดในหลายวิธี (1) มันจะปิดอาร์เรย์โดยที่ @ClintHarris ชี้ให้เห็นดังนั้นจึงไม่ดีไปกว่า. reverse () (2) เครื่องมือเปรียบเทียบของคุณผิดกฎหมาย - เมื่อคุณส่งคืน 1 สำหรับ a, b คุณต้องส่งคืนจำนวนลบสำหรับ b, a หากคำตอบของคุณย้อนกลับอาร์เรย์ในการใช้งานบางอย่างมันเป็นโชคทั้งหมด
Don Hatch
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.