Làm cách nào để thêm các phần tử mảng mới vào đầu một mảng trong Javascript?


1585

Tôi có nhu cầu thêm hoặc thêm các phần tử vào đầu một mảng.

Ví dụ: nếu mảng của tôi trông như dưới đây:

[23, 45, 12, 67]

Và phản hồi từ cuộc gọi AJAX của tôi là 34, tôi muốn mảng được cập nhật như sau:

[34, 23, 45, 12, 67]

Hiện tại tôi đang lên kế hoạch để làm điều đó như thế này:

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

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

theArray = newArray;
delete newArray;

Có cách nào tốt hơn để làm điều này? Javascript có chức năng tích hợp nào thực hiện việc này không?

Sự phức tạp của phương pháp của tôi là O(n)và sẽ rất thú vị khi thấy các triển khai tốt hơn.


9
FYI: Nếu bạn cần liên tục chèn một phần tử vào đầu một mảng, sẽ nhanh hơn khi sử dụng các pushcâu lệnh theo sau là một cuộc gọi đến reverse, thay vì gọi unshifttất cả thời gian.
Jenny O'Reilly

2
@ JennyO'Reilly bạn nên đăng bài này như một câu trả lời. Kết hợp hoàn hảo trường hợp sử dụng của tôi. cảm ơn
cướp

2
Kiểm tra hiệu suất: jsperf.com/adding-element-to-the-array-start Nhưng kết quả khác nhau đối với mỗi trình duyệt.
Avernikoz

Câu trả lời:


2812

Sử dụng unshift. Nó giống như push, ngoại trừ nó thêm các phần tử vào đầu mảng thay vì kết thúc.

  • unshift/ push- thêm một phần tử vào đầu / cuối của một mảng
  • shift/ pop - loại bỏ và trả về phần tử đầu tiên / cuối cùng của một mảng

Một sơ đồ đơn giản ...

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

và biểu đồ:

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

Kiểm tra tài liệu MDN Array . Hầu như mọi ngôn ngữ có khả năng đẩy / bật các phần tử từ một mảng cũng sẽ có khả năng dịch chuyển / dịch chuyển (đôi khi được gọi là push_front/ pop_front), bạn không bao giờ phải tự thực hiện các phần tử này.


Như đã chỉ ra trong các bình luận, nếu bạn muốn tránh làm thay đổi mảng ban đầu của mình, bạn có thể sử dụng concat, nối hai hoặc nhiều mảng lại với nhau. Bạn có thể sử dụng điều này để đẩy một phần tử lên mặt trước hoặc mặt sau của một mảng hiện có; để làm như vậy, bạn cần biến phần tử mới thành một mảng phần tử duy nhất:

const array = [ 3, 2, 1 ]

const newFirstElement = 4

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

concatcũng có thể nối các mục. Các đối số concatcó thể thuộc bất kỳ loại nào; chúng được bao bọc hoàn toàn trong một mảng phần tử đơn, nếu chúng chưa phải là một mảng:

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
Sử dụng concatcó thể được ưa thích hơn vì nó trả về mảng mới. Rất hữu ích cho chuỗi. [thingToInsertToFront].concat(originalArray).reduce(fn).reverse().map(fn)vv ... Nếu bạn sử dụng unshift, bạn không thể thực hiện chuỗi đó bởi vì tất cả những gì bạn nhận được là chiều dài.
StJohn3D

4
thay đổi / không dịch chuyển, đẩy / pop, mối nối. Tên rất logic cho các phương pháp như vậy.
linuxunil

1398

mảng hoạt động hình ảnh

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


117
Lý do tại sao mọi người cần một hướng dẫn trực quan cho 4 chức năng được sử dụng hàng ngày là do các tên hàm được mã hóa ... Tại sao unshift không được gọi là Chèn? Cần thay đổi. v.v ...
Pascal

76
// Tại sao unshift không được gọi là Chèn? // Nó xuất phát từ các quy ước của ngôn ngữ lập trình C nơi các phần tử mảng được xử lý như một ngăn xếp. (xem perlmonks.org/?node_id=613129 để được giải thích đầy đủ)
dreftymac

25
@Pascal Không, chèn và xóa sẽ là tên đặc biệt xấu cho việc này; chúng ngụ ý truy cập ngẫu nhiên, thay vì thêm / xóa từ phía trước của mảng
meagar

25
Tôi đã nghĩ rằng unshift nên loại bỏ khóa đầu tiên và sự thay đổi sẽ chèn vào khóa đầu tiên, nhưng đó chỉ là suy nghĩ chung của tôi
Shannon Hochkins

27
Tôi thích tài liệu tham khảo DNA
Hunter WebDev

235

Với ES6, sử dụng toán tử trải rộng ...:

BẢN GIỚI THIỆU

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

console.log(arr)


19
cũng tạo ra một mảng mới, hữu ích cho các hàm thuần túy
devonj

ý nghĩa hiệu suất ở đây là gì? Có chậm hơn so với sử dụng unshift () không?
Peter T.

1
Chắc chắn, nó sẽ chậm hơn vì nó là một mảng bất biến (tạo ra một mảng mới). Nếu bạn đang làm việc với một mảng lớn hoặc hiệu suất là yêu cầu đầu tiên của bạn, vui lòng xem xét để sử dụng concatthay thế.
Abdennour TOUMI

hiệu suất không quan trọng trong năm 2018, các phiên bản mới trong trình duyệt và nút có cùng hiệu suất
stackdave 16/07/18

75

Một cách khác để làm điều đó thông qua concat

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

Sự khác biệt giữa concatunshiftconcattrả về một mảng mới. Hiệu suất giữa chúng có thể được tìm thấy ở đây .

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

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

Đây là kết quả kiểm tra

nhập mô tả hình ảnh ở đây


Sẽ là tốt cho câu trả lời của bạn để nối so sánh hiệu suất của cả hai ngoài việc thêm tài liệu tham khảo.
Ivan De Paz Centeno

Tôi vừa nhận được jsPerf tạm thời không khả dụng trong khi chúng tôi đang phát hành v2. Vui lòng thử lại sau từ liên kết. Một lý do tốt để bao gồm các kết quả thay vì liên kết với chúng.
Kích hoạt

Kết quả jsPrefunshift :: 25,510 ± 3,18% chậm hơn 99% concat: nhanh nhất 2,436,894 ± 3,39%
Đèn chiếu sáng

Trong Safari mới nhất, fn_unshift () chạy nhanh hơn.
passatgt

Trong Safari mới nhất (v 10), fn_unshift () lại chậm hơn.
rmcsharry

45

Áo choàng nhanh:

Các thuật ngữ shift / unshift và push / pop có thể hơi khó hiểu, ít nhất là với những người không quen thuộc với lập trình trong C.

Nếu bạn không quen thuộc với biệt ngữ, đây là bản dịch nhanh các thuật ngữ thay thế, có thể dễ nhớ hơn:

* 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

bạn có một mảng: var arr = [23, 45, 12, 67];

Để thêm một mục vào đầu, bạn muốn sử dụng splice:

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


mảng.splice (0, Array.length, 34);
Lior Elrom

1
@LiorElrom đoạn trích của bạn làm gì?
Janus Troelsen

@poushy là trình duyệt cụ thể, trong Firefox 54 unshiftnhanh hơn 50% (nhưng chủ yếu dễ đọc hơn)
icl7126

@poushy Không còn nữa. Cách chậm hơn.
Andrew

17

Không có đột biến

Trên thực tế, tất cả unshift/ pushshift/ pop đột biến mảng gốc.

Các unshift/ pushthêm một mục vào mảng tồn tại từ bắt đầu / kết thúc và shift/ popxóa một mục từ đầu / kết thúc của một mảng.

Nhưng có một vài cách để thêm các mục vào một mảng mà không bị đột biến. kết quả là một mảng mới, để thêm vào cuối mảng sử dụng mã bên dưới:

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

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

Để thêm vào để bắt đầu mảng ban đầu, sử dụng mã dưới đây:

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

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

Với cách trên, bạn thêm vào đầu / cuối của một mảng mà không có đột biến.


Tôi chỉ đặt một slicechức năng vào cuối originArrayđể ngăn chặn nó khỏi tính đột biến.
Ahmad Khani

1
Tuyệt vời! Khi nói đến (Redux) Quản lý nhà nước ... câu trả lời này là quý giá!
Pedro Ferreira

1
Đây là cách chính xác!
mmm

10

Sử dụng hàm hủy ES6: (tránh đột biến khỏi mảng ban đầu)

const newArr = [item, ...oldArr]



8

Nếu bạn cần liên tục chèn một phần tử vào đầu một mảng, thì nhanh hơn là sử dụng các pushcâu lệnh theo sau là một cuộc gọi đến reverse, thay vì gọi unshiftmọi lúc.

Kiểm tra điểm chuẩn: http://jsben.ch/kLIYf


1
Lưu ý: mảng ban đầu nên trống.
192kb

5

Sử dụng splicechúng tôi chèn một phần tử vào một mảng tại phần nhận thức:

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

Đó là một câu trả lời đúng. Cảm ơn Srikrushna
Khánh Trần
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.