ฉันจะเพิ่มองค์ประกอบอาร์เรย์ใหม่ที่จุดเริ่มต้นของอาร์เรย์ใน Javascript ได้อย่างไร


1585

ฉันต้องการเพิ่มหรือเสริมองค์ประกอบที่จุดเริ่มต้นของอาร์เรย์

ตัวอย่างเช่นถ้าอาร์เรย์ของฉันดูเหมือนด้านล่าง:

[23, 45, 12, 67]

และการตอบสนองจากการโทร AJAX ของฉันคือ34ฉันต้องการอาร์เรย์ที่อัปเดตให้เป็นดังนี้:

[34, 23, 45, 12, 67]

ขณะนี้ฉันวางแผนที่จะทำเช่นนี้:

var newArray = [];
newArray.push(response);

for (var i = 0; i < theArray.length; i++) {
    newArray.push(theArray[i]);
}

theArray = newArray;
delete newArray;

มีวิธีที่ดีกว่าในการทำเช่นนี้? Javascript มีฟังก์ชั่นในตัวเครื่องหรือไม่?

ความซับซ้อนของวิธีการของฉันคือO(n)และมันน่าสนใจจริงๆที่จะเห็นการใช้งานที่ดีขึ้น


9
FYI: หากคุณต้องการแทรกองค์ประกอบที่จุดเริ่มต้นของอาร์เรย์อย่างต่อเนื่องมันจะเร็วกว่าที่จะใช้pushคำสั่งตามด้วยการเรียกไปที่reverseแทนที่จะเรียกunshiftตลอดเวลา
Jenny O'Reilly

2
@ JennyO'Reilly คุณควรโพสต์สิ่งนี้เป็นคำตอบ จับคู่ case-use ของฉันอย่างสมบูรณ์ ขอบคุณ
rob

2
การทดสอบประสิทธิภาพ: jsperf.com/adding-element-to-the-array-start แต่ผลลัพธ์จะแตกต่างกันสำหรับแต่ละเบราว์เซอร์
Avernikoz

คำตอบ:


2811

unshiftใช้ มันเป็นเหมือนpushยกเว้นจะเพิ่มองค์ประกอบไปยังจุดเริ่มต้นของอาร์เรย์แทนที่จะจบ

  • unshift/ push- เพิ่มองค์ประกอบไปยังจุดเริ่มต้น / จุดสิ้นสุดของอาร์เรย์
  • shift/ pop - ลบและกลับองค์ประกอบแรก / สุดท้ายของอาร์เรย์

แผนภาพอย่างง่าย ...

   unshift -> array <- push
   shift   <- array -> pop

และแผนภูมิ:

          add  remove  start  end
   push    X                   X
    pop           X            X
unshift    X             X
  shift           X      X

ตรวจสอบเอกสารอาร์เรย์ MDN แทบทุกภาษาที่มีความสามารถในการผลัก / อิลิเมนต์ป๊อปจากอาเรย์จะมีความสามารถในการยกเลิกการเลื่อน / เปลี่ยน (บางครั้งเรียกว่าpush_front/ pop_front) องค์ประกอบคุณไม่ควรใช้สิ่งเหล่านี้ด้วยตนเอง


ตามที่ระบุไว้ในความคิดเห็นหากคุณต้องการหลีกเลี่ยงการกลายพันธุ์อาเรย์ดั้งเดิมของคุณคุณสามารถใช้concatซึ่งเชื่อมต่อกันสองอาร์เรย์หรือมากกว่าเข้าด้วยกัน คุณสามารถใช้ฟังก์ชันนี้เพื่อผลักองค์ประกอบเดียวไปยังด้านหน้าหรือด้านหลังของอาร์เรย์ที่มีอยู่ ในการทำเช่นนั้นคุณจะต้องเปลี่ยนองค์ประกอบใหม่เป็นอาร์เรย์องค์ประกอบเดียว:

const array = [ 3, 2, 1 ]

const newFirstElement = 4

const newArray = [newFirstElement].concat(array) // [ 4, 3, 2, 1 ]

concatยังสามารถต่อท้ายรายการ อาร์กิวเมนต์ที่concatสามารถเป็นประเภทใดก็ได้ พวกเขาจะถูกห่อหุ้มโดยนัยในอาร์เรย์องค์ประกอบเดียวหากพวกเขายังไม่ได้อาร์เรย์:

const array = [ 3, 2, 1 ]

const newLastElement  = 0

// Both of these lines are equivalent:
const newArray1 = array.concat(newLastElement)   // [ 3, 2, 1, 0 ]
const newArray2 = array.concat([newLastElement]) // [ 3, 2, 1, 0 ]

51
การใช้concatอาจจะดีกว่าเพราะมันจะส่งกลับอาร์เรย์ใหม่ มีประโยชน์มากสำหรับการผูกมัด [thingToInsertToFront].concat(originalArray).reduce(fn).reverse().map(fn)ฯลฯ ... หากคุณใช้unshiftคุณไม่สามารถผูกมัดได้เพราะสิ่งที่คุณได้รับกลับมาคือความยาว
StJohn3D

4
shift / unshift, push / pop, splice ชื่อตรรกะมากสำหรับวิธีการดังกล่าว
linuxunil

1396

รูปภาพการทำงานของอาร์เรย์

var a = [23, 45, 12, 67];
a.unshift(34);
console.log(a); // [34, 23, 45, 12, 67]


117
เหตุผลที่ผู้คนต้องการคำแนะนำเชิงภาพสำหรับฟังก์ชั่นที่ใช้ประจำวัน 4 รายการเพราะชื่อฟังก์ชั่นเข้ารหัส ... ทำไม unshift จึงไม่เรียกว่าแทรก? Shift ควรเป็น Remove ฯลฯ ...
ปาสกาล

76
// ทำไม unshift ไม่ถูกเรียกว่า Insert? //มันมาจากแบบแผนของภาษาการเขียนโปรแกรม C ที่อิลิเมนต์อาร์เรย์ได้รับการปฏิบัติเหมือนเป็นกองซ้อน (ดูperlmonks.org/?node_id=613129สำหรับคำอธิบายที่สมบูรณ์)
dreftymac

25
@Pascal ไม่การแทรกและการลบจะเป็นชื่อที่ไม่ดีสำหรับสิ่งนี้โดยเฉพาะ พวกเขาหมายถึงการเข้าถึงแบบสุ่มแทนที่จะเพิ่ม / ลบออกจากด้านหน้าของอาร์เรย์
meagar

25
ฉันคิดว่า unshift ควรลบคีย์แรกและ shift จะใส่ที่คีย์แรก แต่นั่นเป็นเพียงความคิดทั่วไปของฉัน
Shannon Hochkins

27
ฉันชอบการอ้างอิง DNA
Hunter WebDev

235

ด้วย ES6 ให้ใช้ตัวดำเนินการสเปรด...:

การสาธิต

var arr = [23, 45, 12, 67];
arr = [34, ...arr]; // RESULT : [34,23, 45, 12, 67]

console.log(arr)


19
สร้างอาเรย์ใหม่ซึ่งมีประโยชน์สำหรับฟังก์ชั่นล้วน ๆ
devonj

ความหมายของประสิทธิภาพที่นี่คืออะไร มันช้ากว่าการใช้ unshift () หรือไม่
Peter T.

1
แน่นอนว่าจะช้าลงเนื่องจากเป็นอาร์เรย์ที่ไม่เปลี่ยนรูป (การสร้างอาร์เรย์ใหม่) หากคุณกำลังทำงานกับอาร์เรย์ขนาดใหญ่หรือประสิทธิภาพเป็นข้อกำหนดแรกของคุณโปรดพิจารณาใช้concatแทน
Abdennour TOUMI

ประสิทธิภาพไม่สำคัญในปี 2018 เวอร์ชั่นใหม่ในเบราว์เซอร์และโหนดจะได้รับประสิทธิภาพที่เหมือนกัน
stackdave

75

อีกวิธีในการทำเช่นนั้นผ่าน concat

var arr = [1, 2, 3, 4, 5, 6, 7];
console.log([0].concat(arr));

ความแตกต่างระหว่างconcatและunshiftคือการconcatส่งคืนอาร์เรย์ใหม่ ผลการดำเนินงานระหว่างพวกเขาอาจจะพบได้ที่นี่

function fn_unshift() {
  arr.unshift(0);
  return arr;
}

function fn_concat_init() {
  return [0].concat(arr)
}

นี่คือผลการทดสอบ

ป้อนคำอธิบายรูปภาพที่นี่


มันจะเป็นการดีสำหรับคำตอบของคุณที่จะผนวกการเปรียบเทียบประสิทธิภาพของทั้งสองนอกเหนือจากการเพิ่มการอ้างอิง
Ivan De Paz Centeno

ฉันเพิ่งได้รับjsPerf ไม่สามารถใช้งานได้ชั่วคราวในขณะที่เรากำลังปล่อย v2 อยู่ โปรดลองอีกครั้งในภายหลังจากลิงค์ อีกเหตุผลที่ดีที่จะรวมผลลัพธ์แทนที่จะเชื่อมโยงไปยังพวกเขา
Tigger

ผล jsPrefunshift : 25,510 ± 3.18% ช้าลง 99% concat: 2,436,894 ± 3.39% เร็วที่สุด
ความกระจ่าง

ใน Safari ล่าสุด fn_unshift () ทำงานได้เร็วขึ้น
passatgt

ใน Safari ล่าสุด (v 10), fn_unshift () ช้าลงอีกครั้ง
rmcsharry

45

Cheatsheet ด่วน:

คำว่า shift / unshift และ push / pop อาจทำให้เกิดความสับสนเล็กน้อยอย่างน้อยสำหรับผู้ที่ไม่คุ้นเคยกับการเขียนโปรแกรมใน C

หากคุณไม่คุ้นเคยกับศัพท์แสงนี่คือคำแปลอย่างรวดเร็วของคำศัพท์ทางเลือกซึ่งอาจจะง่ายต่อการจดจำ:

* array_unshift()  -  (aka Prepend ;; InsertBefore ;; InsertAtBegin )     
* array_shift()    -  (aka UnPrepend ;; RemoveBefore  ;; RemoveFromBegin )

* array_push()     -  (aka Append ;; InsertAfter   ;; InsertAtEnd )     
* array_pop()      -  (aka UnAppend ;; RemoveAfter   ;; RemoveFromEnd ) 

20

คุณมีอาร์เรย์: var arr = [23, 45, 12, 67];

ในการเพิ่มรายการไปยังจุดเริ่มต้นคุณต้องการใช้splice:

var arr = [23, 45, 12, 67];
arr.splice(0, 0, 34)
console.log(arr);


arr.splice (0, arr.length, 34);
Lior Elrom

1
@ LiorElrom ข้อมูลโค้ดของคุณทำอะไร
Janus Troelsen

@poushy เป็นเบราว์เซอร์ที่เฉพาะเจาะจงใน Firefox 54 จะunshiftเร็วขึ้น 50% (แต่ส่วนใหญ่อ่านได้มากขึ้น)
icl7126

@poushy ไม่อีกแล้ว วิธีที่ช้าลง
แอนดรู

17

โดยไม่ต้องกลายพันธุ์

ที่จริงแล้วทั้งหมดunshift/ pushและshift/ pop กลายพันธุ์อาเรย์ต้นกำเนิด

กระบวนการunshift/ pushเพิ่มรายการไปยังอาร์เรย์ที่มีอยู่ตั้งแต่เริ่มต้น / สิ้นสุดและshift/ popลบรายการออกจากจุดเริ่มต้น / สิ้นสุดของอาร์เรย์

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

const originArray = ['one', 'two', 'three'];
const newItem = 4;

const newArray = originArray.concat(newItem); // ES5
const newArray2 = [...originArray, newItem]; // ES6+

ในการเพิ่มไปยังจุดเริ่มต้นของอาร์เรย์เดิมให้ใช้รหัสด้านล่าง:

const originArray = ['one', 'two', 'three'];
const newItem = 0;

const newArray = (originArray.slice().reverse().concat(newItem)).reverse(); // ES5
const newArray2 = [newItem, ...originArray]; // ES6+

ด้วยวิธีการข้างต้นคุณเพิ่มไปยังจุดเริ่มต้น / จุดสิ้นสุดของอาร์เรย์โดยไม่มีการกลายพันธุ์


ฉันเพิ่งวางsliceฟังก์ชั่นไว้ท้ายสุดoriginArrayเพื่อป้องกันไม่ให้เกิดความไม่แน่นอน
Ahmad Khani

1
! น่ากลัว เมื่อมาถึง (Redux) การจัดการของรัฐ ... คำตอบนี้มีค่า!
Pedro Ferreira

1
นี่เป็นวิธีที่ถูกต้อง!
mmm

10

ใช้การทำลายโครงสร้าง ES6: (หลีกเลี่ยงการกลายพันธุ์ของอาร์เรย์เดิม)

const newArr = [item, ...oldArr]



8

หากคุณต้องการแทรกองค์ประกอบที่จุดเริ่มต้นของอาร์เรย์อย่างต่อเนื่องมันจะเร็วกว่าที่จะใช้pushคำสั่งตามด้วยการเรียกไปที่reverseแทนที่จะเรียกunshiftตลอดเวลา

การทดสอบเกณฑ์มาตรฐาน: http://jsben.ch/kLIYf


1
หมายเหตุ: อาร์เรย์เริ่มต้นควรว่างเปล่า
192kb

5

การใช้spliceเราใส่องค์ประกอบเข้าไปในอาร์เรย์ที่สิ่งที่น่าสนใจ:

arrName.splice( 0, 0, 'newName1' );

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