Câu hỏi Làm thế nào để chèn một mục vào một mảng tại một chỉ mục cụ thể?


Tôi đang tìm phương thức chèn mảng Javascript, theo kiểu:

arr.insert(index, item)

Tốt hơn là trong jQuery, nhưng bất kỳ triển khai Javascript nào cũng sẽ thực hiện tại thời điểm này.


2081
2018-02-25 14:29


gốc


Lưu ý rằng JQuery là một thư viện thao tác DOM và sự kiện, không phải là ngôn ngữ của riêng nó. Nó không liên quan gì đến thao tác mảng. - Jacque Goupil
api.jquery.com/jQuery.inArray không liên quan gì đến DOM hoặc sự kiện. jQuery đã phát triển thành một bộ công cụ hỗn hợp để phát triển JS trong trình duyệt, dẫn đến những người mong đợi nó có một phương thức cho mọi thứ. - Tim
@Tim, Nhưng nó vẫn không phải là một ngôn ngữ riêng của mình (vẫn còn có một số câu hỏi như "làm thế nào để tổng hợp hai con số trong jQuery" ở đây trên SO) - Victor
@Victor Không, và sẽ không bao giờ. jQuery là hữu ích và có liên quan, nhưng nó đã có ngày của nó. - Tim


Các câu trả lời:


Những gì bạn muốn là splice trên đối tượng mảng gốc.

arr.splice(index, 0, item); sẽ chèn item vào arr tại chỉ mục được chỉ định (xóa 0 các mục đầu tiên, nghĩa là, nó chỉ là một chèn).

Trong ví dụ này, chúng ta sẽ tạo một mảng và thêm một phần tử vào nó vào chỉ mục 2:

var arr = [];
arr[0] = "Jani";
arr[1] = "Hege";
arr[2] = "Stale";
arr[3] = "Kai Jim";
arr[4] = "Borge";

console.log(arr.join());
arr.splice(2, 0, "Lene");
console.log(arr.join());


3447
2018-02-25 14:32



Cảm ơn, tôi nghĩ tôi sẽ cảm thấy ngớ ngẩn khi hỏi nhưng bây giờ tôi biết câu trả lời tôi không biết! Tại sao họ lại quyết định gọi nó là mối liên kết khi một thuật ngữ có thể tìm kiếm được sử dụng phổ biến cho cùng một chức năng ?! - tags2k
@ tags2k: bởi vì chức năng không nhiều hơn chèn các mục và tên của nó đã được thiết lập trong perl? - Christoph
doc: developer.mozilla.org/en/JavaScript/Guide/… - Dingo
Splice có thể chèn, nhưng cũng giống như thường xuyên không làm. Ví dụ: arr.splice(2,3) sẽ loại bỏ 3 phần tử bắt đầu từ chỉ mục 2. Không truyền tham số thứ 3 .... Nth, không có tham số nào được chèn vào. Vì vậy, tên insert() cũng không làm điều đó. - EBarr
Tôi nghĩ thuật ngữ "mối nối" có ý nghĩa. Splice có nghĩa là để tham gia hoặc kết nối, cũng để thay đổi. Bạn có một mảng đã được thiết lập mà bây giờ bạn đang "thay đổi" sẽ liên quan đến việc thêm hoặc loại bỏ các phần tử. Bạn chỉ định vị trí trong mảng bắt đầu, sau đó có bao nhiêu mục cũ cần xóa (nếu có) và cuối cùng, tùy chọn danh sách các phần tử mới cần thêm. Splice cũng là một thuật ngữ khoa học viễn tưởng tuyệt vời. - Jakub Keller


Bạn có thể thực hiện Array.insert phương pháp bằng cách thực hiện điều này:

Array.prototype.insert = function ( index, item ) {
    this.splice( index, 0, item );
};

Sau đó, bạn có thể sử dụng nó như:

var arr = [ 'A', 'B', 'D', 'E' ];
arr.insert(2, 'C');

// => arr == [ 'A', 'B', 'C', 'D', 'E' ]

208
2017-10-03 14:26



Không sửa đổi các đối tượng bạn không sở hữu - Pavlo
Ai sở hữu Array? ECMA script comitee? Tôi có nghĩa là nếu bạn làm điều đó với Object.defineProperty nó có thể không phải là xấu như Pavlo nghĩ rằng nó được. - Capaj
Để chèn nhiều mục bạn có thể sử dụng Array.prototype.insert = function (index, items) { this.splice.apply(this, [index, 0].concat(items)); } - Ryan Smith
Vấn đề với việc thêm công cụ vào mảng là hàm sẽ hiển thị dưới dạng phần tử khi bạn thực hiện (i in arr) {...} - rep_movsd
Những gì Pavlo đang nói là - nếu phương thức chèn gốc được triển khai, hoặc 2 hoặc nhiều nhà phát triển trong công ty của bạn sẽ có ý tưởng tạo chèn cho đối tượng mảng nhưng việc triển khai sẽ khác ... Bạn có ý tưởng. - Adam Moszczyński


Mảng tùy chỉnh insert phương pháp

1. Với nhiều đối số và hỗ trợ chuỗi

/* Syntax:
   array.insert(index, value1, value2, ..., valueN) */

Array.prototype.insert = function(index) {
    this.splice.apply(this, [index, 0].concat(
        Array.prototype.slice.call(arguments, 1)));
    return this;
};

Nó có thể chèn nhiều yếu tố (như là bản địa splice hiện) và hỗ trợ chuỗi:

["a", "b", "c", "d"].insert(2, "X", "Y", "Z").slice(1, 6);
// ["b", "X", "Y", "Z", "c"]

2. Với các đối số kiểu mảng hợp nhất và hỗ trợ chuỗi

/* Syntax:
   array.insert(index, value1, value2, ..., valueN) */

Array.prototype.insert = function(index) {
    index = Math.min(index, this.length);
    arguments.length > 1
        && this.splice.apply(this, [index, 0].concat([].pop.call(arguments)))
        && this.insert.apply(this, arguments);
    return this;
};

Nó có thể hợp nhất các mảng từ các đối số với mảng đã cho và cũng hỗ trợ chuỗi:

["a", "b", "c", "d"].insert(2, "V", ["W", "X", "Y"], "Z").join("-");
// "a-b-V-W-X-Y-Z-c-d"

BẢN GIỚI THIỆU:  http://jsfiddle.net/UPphH/


64
2018-03-25 17:45



Có một cách nhỏ gọn để có phiên bản này cũng hợp nhất một mảng khi nó tìm thấy một trong các đối số? - Nolo
@Nolo Có, bạn có thể tìm thấy nó trong câu trả lời được cập nhật. - VisioN
Tôi không hiểu kết quả đầu tiên ["b", "X", "Y", "Z", "c"]. Tại sao không "d" bao gồm? Dường như với tôi rằng nếu bạn đặt 6 là tham số thứ hai của slice() và có 6 phần tử trong mảng bắt đầu từ chỉ mục được chỉ định, khi đó bạn sẽ nhận được tất cả 6 phần tử trong giá trị trả lại. (Tài liệu nói howMany cho tham số đó.) developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… - Alexis Wilke
Trên thực tế, nếu tôi sử dụng chỉ mục từ 3 trở lên, tôi sẽ không nhận được gì trong đầu ra (trường hợp 1., FireFox) ["a", "b", "c", "d"].insert(2, "X", "Y", "Z").slice(3, 3); => [ ] - Alexis Wilke
@AlexisWilke Trong ví dụ đầu tiên tôi đã sử dụng slice phương pháp và không splicemà bạn đang đề cập đến trong nhận xét. Tham số thứ hai của slice (có tên end) Là chỉ số dựa trên zero để kết thúc quá trình trích xuất. slice chiết xuất đến nhưng không bao gồm end. Do đó sau insert bạn có ["a", "b", "X", "Y", "Z", "c", "d"], từ đó slice chiết xuất các phần tử có chỉ số từ 1 lên đến 6, tức là từ "b" đến "d" nhưng không bao gồm "d". Nó có ý nghĩa không? - VisioN


Khác với mối nối, bạn có thể sử dụng cách tiếp cận này sẽ không làm biến đổi mảng ban đầu, nhưng sẽ tạo một mảng mới với mục được thêm vào. Bạn thường nên tránh đột biến bất cứ khi nào có thể. Tôi đang sử dụng ES6 lây lan nhà điều hành ở đây.

const items = [1, 2, 3, 4, 5]

const insert = (arr, index, newItem) => [
  // part of the array before the specified index
  ...arr.slice(0, index),
  // inserted item
  newItem,
  // part of the array after the specified index
  ...arr.slice(index)
]

const result = insert(items, 1, 10)

console.log(result)
// [1, 10, 2, 3, 4, 5]

Điều này có thể được sử dụng để thêm nhiều hơn một mục bằng cách tinh chỉnh chức năng một chút để sử dụng toán tử còn lại cho các mục mới và trải đều trong kết quả trả về

const items = [1, 2, 3, 4, 5]

const insert = (arr, index, ...newItems) => [
  // part of the array before the specified index
  ...arr.slice(0, index),
  // inserted items
  ...newItems,
  // part of the array after the specified index
  ...arr.slice(index)
]

const result = insert(items, 1, 10, 20)

console.log(result)
// [1, 10, 20, 2, 3, 4, 5]


54
2017-07-04 09:18



chính xác câu trả lời tôi đang tìm kiếm. cảm ơn bạn! - Alex Alexeev
Đây có phải là cách tốt, an toàn để thực hiện việc này không? Tôi hỏi vì điều này có vẻ rất thanh lịch và ngắn gọn nhưng không có câu trả lời nào khác liên quan đến điều này. Hầu hết trong số họ sửa đổi đối tượng nguyên mẫu! - Harsh Kanchina
@ HarshKanchina Đó có lẽ là vì hầu hết các câu trả lời đều là ES6 trước, nhưng cách tiếp cận này rất phổ biến hiện nay từ trải nghiệm của tôi - Gaafar


Nếu bạn muốn chèn nhiều phần tử vào một mảng cùng một lúc, hãy kiểm tra câu trả lời Stack Overflow này: Một cách tốt hơn để ghép một mảng vào một mảng trong javascript

Ngoài ra, đây là một số chức năng để minh họa cho cả hai ví dụ:

function insertAt(array, index) {
    var arrayToInsert = Array.prototype.splice.apply(arguments, [2]);
    return insertArrayAt(array, index, arrayToInsert);
}

function insertArrayAt(array, index, arrayToInsert) {
    Array.prototype.splice.apply(array, [index, 0].concat(arrayToInsert));
    return array;
}

Cuối cùng, đây là một jsFiddle để bạn có thể thấy nó cho chính mình: http://jsfiddle.net/luisperezphd/Wc8aS/

Và đây là cách bạn sử dụng các chức năng:

// if you want to insert specific values whether constants or variables:
insertAt(arr, 1, "x", "y", "z");

// OR if you have an array:
var arrToInsert = ["x", "y", "z"];
insertArrayAt(arr, 1, arrToInsert);

33
2017-08-30 04:37



Sẽ không insertAt () làm tốt hơn để gọi insertArrayAt () một khi nó đã tạo ra một arrayToInsert phần tử đơn? Điều đó tránh lặp lại mã giống hệt nhau. - Matt Sach
đây là một ví dụ tuyệt vời về thời điểm sử dụng 'áp dụng' - CRice
Tôi đã thêm một tham số removeCount vào phương thức này để tận dụng khả năng của splice cũng có thể loại bỏ các mục tại chỉ mục đó: Array.prototype.splice.apply (mảng, [index, removeCount || 0] .concat (arrayToInsert)); - CRice


Để lập trình chức năng thích hợp và các mục đích chuỗi một phát minh Array.prototype.insert() là điều cần thiết. Trên thực tế mối nối có thể đã được hoàn hảo nếu nó đã trả về mảng đột biến thay vì một mảng trống hoàn toàn vô nghĩa. Vì vậy, ở đây nó đi

Array.prototype.insert = function(i,...rest){
  this.splice(i,0,...rest)
  return this
}

var a = [3,4,8,9];
document.write("<pre>" + JSON.stringify(a.insert(2,5,6,7)) + "</pre>");

Vâng ok ở trên với Array.prototype.splice() một trong những biến đổi mảng ban đầu và một số có thể khiếu nại như "bạn không nên sửa đổi những gì không thuộc về bạn" và điều đó có thể bật ra là đúng là tốt. Vì vậy, đối với phúc lợi công cộng, tôi muốn cung cấp cho người khác Array.prototype.insert() không biến đổi mảng ban đầu. Nó đi từ đây;

Array.prototype.insert = function(i,...rest){
  return this.slice(0,i).concat(rest,this.slice(i));
}

var a = [3,4,8,9],
    b = a.insert(2,5,6,7);
console.log(JSON.stringify(a));
console.log(JSON.stringify(b));


14
2018-05-13 23:22



"một mảng rỗng hoàn toàn vô nghĩa" - nó chỉ trả về một mảng trống khi tham số thứ hai là 0. Nếu nó lớn hơn 0, nó trả về các mục đã bị loại bỏ khỏi mảng. Cho rằng bạn đang thêm vào một mẫu thử nghiệm và splice biến đổi mảng ban đầu, tôi không nghĩ rằng "lập trình chức năng thích hợp" thuộc bất kỳ nơi nào trong vùng lân cận splice. - cdbajorin
Chúng ta đang nói về chèn ở đây và tham số thứ hai của Array.prototype.splice () phải bằng không. Và những gì nó trả về không có ý nghĩa khác hơn là "tôi đã không xóa bất cứ điều gì" và kể từ khi chúng tôi sử dụng nó để chèn một mục chúng tôi đã có thông tin đó. Nếu bạn không muốn thay đổi mảng ban đầu thì bạn có thể làm tương tự với hai Array.prototype.slice () và một hoạt động Array.prototype.concat (). Tuỳ bạn. - Redu
Việc triển khai thứ hai của bạn là sạch nhất từ ​​toàn bộ trang này và bạn không có phiếu bầu nào. Hãy lấy của tôi và theo kịp công việc tốt. (bạn nên tránh biến đổi nguyên mẫu nhưng bạn đã biết điều đó) - NiKo
Tôi nghĩ rằng điều đáng nói đến là tham số còn lại là ECMA thứ 6 mới (developer.mozilla.org/en/docs/Web/JavaScript/Reference/… ) - Geza Turi


Tôi khuyên bạn nên sử dụng tinh khiết JavaScript trong trường hợp này, cũng không có phương thức chèn trong JavaScript, nhưng chúng ta có một phương thức Mảng tích hợp phương pháp thực hiện công việc cho bạn, nó được gọi là mối nối...

Hãy xem những gì mối nối ()...

Phương thức splice () thay đổi nội dung của một mảng bằng cách loại bỏ   các phần tử hiện có và / hoặc thêm các phần tử mới.

OK, hãy tưởng tượng chúng ta có mảng này bên dưới:

const arr = [1, 2, 3, 4, 5];

Chúng ta có thể loại bỏ 3 như thế này:

arr.splice(arr.indexOf(3), 1);

Nó sẽ trả về 3, nhưng nếu chúng ta kiểm tra arr bây giờ, chúng ta có:

[1, 2, 4, 5]

Cho đến nay, rất tốt, nhưng làm thế nào chúng ta có thể thêm một phần tử mới vào mảng bằng cách sử dụng mối nối? Hãy đặt lại 3 trong arr ...

arr.splice(2, 0, 3);

Hãy xem những gì chúng tôi đã làm ...

Chúng tôi sử dụng mối nối một lần nữa, nhưng lần này cho đối số thứ hai, chúng ta vượt qua 0, có nghĩa là chúng tôi muốn xóa không có mục nào, nhưng đồng thời, chúng tôi thêm đối số thứ ba là 3 sẽ được thêm vào chỉ mục thứ hai ...

Bạn nên biết rằng chúng ta có thể xóa bỏ và thêm vào cùng một lúc, ví dụ bây giờ chúng ta có thể làm:

arr.splice(2, 2, 3);

Mà sẽ xóa 2 mục tại chỉ mục 2, sau đó thêm 3 tại chỉ số 2 và kết quả sẽ là:

[1, 2, 3, 5];

Điều này cho thấy mỗi mục trong mối nối hoạt động như thế nào:

array.splice (bắt đầu, deleteCount, item1, item2, item3 ...)


7
2017-12-25 13:04





Một giải pháp khả thi khác, với việc sử dụng Array#reduce.

var arr = ["apple", "orange", "raspberry"],
    arr2 = [1, 2, 4];

function insert(arr, item, index) {
    arr = arr.reduce(function(s, a, i) {
      i == index ? s.push(item, a) : s.push(a);
      return s;
    }, []);   
    console.log(arr);
}

insert(arr, "banana", 1);
insert(arr2, 3, 2);


5
2018-04-05 17:06