Cách hiệu quả nhất để nối các mảng N là gì?


Câu trả lời:


323

Nếu bạn đang nối nhiều hơn hai mảng, đó concat()là cách để thuận tiện và có khả năng thực hiện.

var a = [1, 2], b = ["x", "y"], c = [true, false];
var d = a.concat(b, c);
console.log(d); // [1, 2, "x", "y", true, false];

Để ghép chỉ hai mảng, thực tế là pushchấp nhận nhiều đối số bao gồm các phần tử để thêm vào mảng thay vào đó để thêm các phần tử từ một mảng vào cuối mảng khác mà không tạo ra một mảng mới. Với slice()nó cũng có thể được sử dụng thay thế concat()nhưng dường như không có lợi thế về hiệu suất từ ​​việc này .

var a = [1, 2], b = ["x", "y"];
a.push.apply(a, b);
console.log(a); // [1, 2, "x", "y"];

Trong ECMAScript 2015 trở lên, điều này có thể được giảm hơn nữa đến

a.push(...b)

Tuy nhiên, dường như đối với các mảng lớn (có thứ tự từ 100.000 thành viên trở lên), kỹ thuật chuyển một mảng các phần tử sang push(sử dụng apply()hoặc toán tử trải ECMAScript 2015) có thể thất bại. Đối với các mảng như vậy, sử dụng một vòng lặp là một cách tiếp cận tốt hơn. Xem https://stackoverflow.com/a/17368101/96100 để biết chi tiết.


1
Tôi tin rằng thử nghiệm của bạn có thể có lỗi: a.concat(b)trường hợp thử nghiệm dường như không cần thiết phải tạo một bản sao của mảng asau đó ném nó đi.
ninjagecko

1
@ninjagecko: Bạn nói đúng. Tôi đã cập nhật nó: jsperf.com/concatperftest/6 . Đối với trường hợp cụ thể tạo một mảng mới nối hai mảng hiện có, nó concat()thường xuất hiện nhanh hơn. Đối với trường hợp ghép một mảng lên một mảng hiện có, push()là cách để đi. Tôi cập nhật câu trả lời của tôi.
Tim Down

16
Tôi có thể chứng thực rằng việc mở rộng một mảng với một vài mảng mới bằng phương thức push.apply mang lại lợi thế hiệu năng rất lớn (~ 100x) so với lệnh gọi concat đơn giản. Tôi đang xử lý danh sách rất dài các danh sách ngắn về số nguyên, trong v8 / node.js.
chbrown

1
Một cách ngắn gọn hơn nữa là a.push (... b);
dinvlad

1
@dinvlad: Đúng, nhưng chỉ trong môi trường ES6. Tôi đã thêm một ghi chú vào câu trả lời của tôi.
Tim Down

158
[].concat.apply([], [array1, array2, ...])

chỉnh sửa : bằng chứng về hiệu quả: http://jsperf.com/multi-array-concat/7

edit2 : Tim Supinie đề cập trong các ý kiến rằng điều này có thể gây ra các thông dịch viên để vượt quá kích thước gọi stack. Điều này có lẽ phụ thuộc vào công cụ js, nhưng tôi cũng đã nhận được "vượt quá kích thước ngăn xếp cuộc gọi tối đa" trên Chrome. Trường hợp thử nghiệm : [].concat.apply([], Array(300000).fill().map(_=>[1,2,3])). .


3
@ c69: có vẻ như hiệu quả như câu trả lời được chọn của nhiều lần .push (#, #, ..., #), trên Chrome ít nhất. jsperf.com/multi-array-concat Câu trả lời được lựa chọn của Tim Down cũng có thể có lỗi trong đó. Liên kết này là một so sánh hiệu suất của việc tham gia nhiều mảng như câu hỏi được hỏi (không chỉ 2); nhiều độ dài có thể được thử nghiệm.
ninjagecko

IMO đây là cách hiệu quả nhất để "hợp nhất" n mảng, được thực hiện tốt
Eric Uldall 17/03/2016

Câu trả lời này đặc biệt hữu ích khi N không được biết trước như khi bạn có một mảng các mảng có độ dài tùy ý và bạn muốn tất cả chúng được nối với nhau.
jfriend00

3
Với ES6 và các toán tử trải rộng, nó thậm chí còn đơn giản hơn: [] .concat (... [mảng1, mảng2, ...]) Chà, ba dấu chấm thứ hai hơi đáng tiếc. Ba đầu tiên là các nhà điều hành lây lan developer.mozilla.org/en/docs/Web/JavaScript/Reference/...
Eydrian

Eydrian: Cá nhân tôi cố gắng tránh toán tử lây lan vì nó rất kém hiệu quả, nhưng tôi không chắc nếu đó là do việc triển khai chưa trưởng thành hay ngữ nghĩa của đặc tả es6 đòi hỏi một chút nâng nặng hơn (nghĩa là nó sẽ không bao giờ tốt hơn ). Không chạy bất kỳ điểm chuẩn nào trong trường hợp cụ thể này.
ninjagecko

34

Đối với những người sử dụng ES2015 (ES6)

Bây giờ bạn có thể sử dụng Cú pháp trải rộng để nối các mảng:

const arr1 = [0, 1, 2],
      arr2 = [3, 4, 5];

const result1 = [...arr1, ...arr2]; // -> [0, 1, 2, 3, 4, 5]

// or...

const result2 = [...arr2, ...arr1]; // -> [3, 4, 5, 0, 1, 2]

Làm thế nào là hiệu quả này? Từ những gì tôi đã kiểm tra, điều này rất chậm đối với các mảng chứa các đối tượng, xem: jsperf.com/array-concat-vs-array-push-vs-array-s lây / 1
hitautodesturation

28

Các concat()phương pháp được sử dụng để nối hai hoặc nhiều mảng. Nó không thay đổi các mảng hiện có, nó chỉ trả về một bản sao của các mảng đã tham gia.

array1 = array1.concat(array2, array3, array4, ..., arrayN);

1
Đôi khi tôi ghét JavaScript vì không điều chỉnh mảng gốc. 🙄
Vincent Hoch-Drei

@ VincentHoch-Drei concatđược sử dụng đặc biệt để tạo các mảng mới mà không làm thay đổi mảng ban đầu. Nếu bạn muốn cập nhật array1, bạn phải sử dụngarray1.push(...array2, ...array3, ...array4)
adiga

24

Sử dụng Array.prototype.concat.apply để xử lý kết nối nhiều mảng:

var resultArray = Array.prototype.concat.apply([], arrayOfArraysToConcat);

Thí dụ:

var a1 = [1, 2, 3],
    a2 = [4, 5],
    a3 = [6, 7, 8, 9];
Array.prototype.concat.apply([], [a1, a2, a3]); // [1, 2, 3, 4, 5, 6, 7, 8, 9]

1
Tôi thích cái này! Hoạt động dễ dàng với một số lượng các mảng khác nhau để nối. +1
Joel

14

Nếu bạn đang ở giữa đường ống kết quả thông qua ánh xạ / bộ lọc / sắp xếp, v.v. và bạn muốn nối các mảng của mảng, bạn có thể sử dụng reduce

let sorted_nums = ['1,3', '4,2']
  .map(item => item.split(','))   // [['1', '3'], ['4', '2']]
  .reduce((a, b) => a.concat(b))  // ['1', '3', '4', '2']
  .sort()                         // ['1', '2', '3', '4']

14

Đối với mảng nhiều mảng và ES6, hãy sử dụng

Array.prototype.concat(...arr);

Ví dụ:

const arr = [[1, 2, 3], [4, 5, 6], [7, 8 ,9]];
const newArr = Array.prototype.concat(...arr);
// output: [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

1
Ngoài ra, bạn có thể loại bỏ các yếu tố trùng lặp bằng cách sử dụng newArr = Array.from(new Set(newArr));.
Darius M.

Tại sao trong bản in này lại trở thành any[]? Việc đánh máy là ở đó - kỳ lạ.
Simon_Weaver

Điều này thực sự không hiệu quả khủng khiếp ở khối lượng mảng lớn hơn. jsperf.com/flatten-array-203948 [].concat.apply([], ...arr) thực hiện tốt hơn rất nhiều với khối lượng lớn.
colemars

7

Bây giờ chúng ta có thể kết hợp nhiều mảng bằng cách sử dụng ES6 Spread. Thay vì sử dụng concat()để nối các mảng, hãy thử sử dụng cú pháp trải rộng để kết hợp nhiều mảng thành một mảng phẳng. ví dụ:

var a = [1,2];
var b = [3,4];
var c = [5,6,7];
var d = [...a, ...b, ...c];
// resulting array will be like d = [1,2,3,4,5,6,7]

5

giải quyết như thế này

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

Giải pháp hoàn hảo.
nehem

4

Bạn có thể sử dụng trang web jsperf.com để so sánh độ hoàn hảo. Đây là liên kết đến concat .

Đã thêm so sánh giữa:

var c = a.concat(b);

và:

var c = [];
for (i = 0; i < a.length; i++) {
    c.push(a[i]);
}
for (j = 0; j < b.length; j++) {
    c.push(b[j]);
}

Thứ hai là chậm hơn gần 10 lần trong chrome.


Tuy nhiên, bạn có thể sử dụng push.apply(), dường như nhanh hơn concat()trong tất cả các trình duyệt ngoại trừ Chrome. Xem câu trả lời của tôi.
Tim Down


3

Đây là một hàm mà bạn có thể ghép nhiều số mảng

function concatNarrays(args) {
    args = Array.prototype.slice.call(arguments);
    var newArr = args.reduce( function(prev, next) {
       return prev.concat(next) ;
    });

    return newArr;
}

Thí dụ -

console.log(concatNarrays([1, 2, 3], [5, 2, 1, 4], [2,8,9]));

sẽ xuất

[1,2,3,5,2,1,4,2,8,9]

2

Nếu bạn có mảng mảng và muốn ghép các phần tử thành một mảng duy nhất, hãy thử đoạn mã sau (Yêu cầu ES2015):

let arrOfArr = [[1,2,3,4],[5,6,7,8]];
let newArr = [];
for (let arr of arrOfArr) {
    newArr.push(...arr);
}

console.log(newArr);
//Output: [1,2,3,4,5,6,7,8];

Hoặc nếu bạn tham gia lập trình chức năng

let arrOfArr = [[1,2,3,4],[5,6,7,8]];
let newArr = arrOfArr.reduce((result,current)=>{
    result.push(...current);
    return result;
});

console.log(newArr);
//Output: [1,2,3,4,5,6,7,8];

Hoặc thậm chí tốt hơn với cú pháp ES5, không có toán tử trải

var arrOfArr = [[1,2,3,4],[5,6,7,8]];
var newArr = arrOfArr.reduce((result,current)=>{
    return result.concat(current);
});
console.log(newArr);
//Output: [1,2,3,4,5,6,7,8];

Cách này rất hữu ích nếu bạn không biết không. của mảng tại thời điểm mã.


2

Rút ngắn với ES6.

new Set([].concat(...Array));

Điều này không concatduy nhất nhiều mảng;

Bản demo trên codepen


nó làm nhưng nó loại bỏ các bản sao .. nếu tôi không muốn loại bỏ các mảng trùng lặp thì sao?
Krunal Shah

new Set()không loại bỏ các mục trùng lặp. Chỉ cần loại bỏ nó. [].concat(...Array)
ronaldtgi

tôi muốn sử dụng Set mới ([]. concat (... Array)); nhưng tôi cũng muốn loại bỏ các bản sao cùng với nó trong một biểu thức. có thể không
Krunal Shah

2

Hợp nhất mảng với đẩy:

const array1 = [2, 7, 4];
const array2 = [3, 5,9];
array1.push(...array2);
console.log(array1)

Sử dụng toán tử concatSpread:

const array1 = [1,2];
const array2 = [3,4];

// Method 1: Concat 
const combined1 = [].concat(array1, array2);

// Method 2: Spread
const combined2 = [...array1, ...array2];

console.log(combined1);
console.log(combined2);


1

trong đó 'n' là một số mảng, có thể là một mảng của mảng. . .

var answer = _.reduce (n, hàm (a, b) {return a.concat (b)})



0

thử cái này:

i=new Array("aaaa", "bbbb");
j=new Array("cccc", "dddd");

i=i.concat(j);

@reggie, cả hai bạn đã sao chép từ cùng một nguồn;)
I.devries

không tôi đã kiểm tra thông tin trong cùng một liên kết mà bạn. ilovethecode.com/Javascript/Javascript-Tutorials-How_To-Easy/...
Jairo

vâng ... Tôi đoán chúng tôi đã lấy nó từ cùng một nguồn: D
reggie

ít nhất @JAiro đã thay đổi nội dung mảng. @reggie thì không. :)
dogbane

cũng vậy, điều quan trọng là giúp mọi người giải quyết vấn đề của mình :)
JAiro

0

nếu mảng N được lấy từ cơ sở dữ liệu và không được mã hóa cứng, tôi sẽ làm như thế này bằng ES6

let get_fruits = [...get_fruits , ...DBContent.fruit];
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.