Cách chia một mảng dài thành các mảng nhỏ hơn với JavaScript


98

Tôi có một mảng e-mail (nó có thể chỉ là 1 email hoặc 100 email) và tôi cần gửi mảng với một yêu cầu ajax (mà tôi biết cách làm), nhưng tôi chỉ có thể gửi một mảng có 10 hoặc ít hơn e-mail trong đó. Vì vậy, nếu có một mảng ban đầu gồm 20 e-mail, tôi sẽ cần phải chia chúng thành 2 mảng, mỗi mảng 10 e-mail. hoặc nếu có 15 e-mail trong mảng ban đầu, sau đó là 1 mảng 10 và một mảng khác là 5. Tôi đang sử dụng jQuery, cách tốt nhất để làm điều này là gì?

Câu trả lời:


194

Không sử dụng jquery ... sử dụng javascript thuần túy

var a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];

var b = a.splice(0,10);

//a is now [11,12,13,14,15];
//b is now [1,2,3,4,5,6,7,8,9,10];

Bạn có thể lặp lại điều này để có được hành vi bạn muốn.

var a = YOUR_ARRAY;
while(a.length) {
    console.log(a.splice(0,10));
}

Điều này sẽ cung cấp cho bạn 10 phần tử cùng một lúc ... nếu bạn nói 15 phần tử, bạn sẽ nhận được 1-10, 11-15 như bạn muốn.


9
Lưu ý rằng YOUR_ARRAY sẽ được tiêu thụ cũng như (mảng là đối tượng ...)
Claudio

Vâng, tôi chỉ đặt điều đó vì a không mang tính mô tả, và tôi đã viết ví dụ bằng cách sử dụng ... nó là một dòng mã hoàn toàn không cần thiết ... Mặc dù, điều đó khiến tôi nghĩ ... nếu sử dụng mẫu này, bạn có thể muốn làm một bản sao sâu vào một mảng làm việc như để không phá vỡ bạn gốc
jyore

@junvar IDK nếu 1 lớp lót đó hoạt động vào năm 2018 (tôi thực sự nghi ngờ điều đó), nhưng nó đã thất bại thảm hại hôm nay. Bạn không bao giờ nên thay đổi (tức là loại bỏ các phần tử) một mảng đang được lặp lại, nó sẽ loại bỏ chỉ mục, tức là sau mỗi lần xóa, nó sẽ được điều chỉnh lại theo số lượng phần tử bị loại bỏ, vì vậy nó "bỏ qua" và không sử dụng mảng hoàn toàn. Hãy thử nó
Drew Reese

107
var size = 10; var arrayOfArrays = [];
for (var i=0; i<bigarray.length; i+=size) {
     arrayOfArrays.push(bigarray.slice(i,i+size));
}
console.log(arrayOfArrays);

Không giống như splice(), slice()không phá hủy mảng ban đầu.


1
giải pháp này tốt hơn
Maduekwe Pedro

38

Chỉ cần lặp qua mảng, nối nó cho đến khi nó được tiêu thụ hết.



var a = ['a','b','c','d','e','f','g']
  , chunk

while (a.length > 0) {

  chunk = a.splice(0,3)

  console.log(chunk)

}

đầu ra


[ 'a', 'b', 'c' ]
[ 'd', 'e', 'f' ]
[ 'g' ]



13

Giả sử bạn không muốn phá hủy mảng ban đầu, bạn có thể sử dụng mã như thế này để chia mảng dài thành các mảng nhỏ hơn mà sau đó bạn có thể lặp lại:

var longArray = [];   // assume this has 100 or more email addresses in it
var shortArrays = [], i, len;

for (i = 0, len = longArray.length; i < len; i += 10) {
    shortArrays.push(longArray.slice(i, i + 10));
}

// now you can iterate over shortArrays which is an 
// array of arrays where each array has 10 or fewer 
// of the original email addresses in it

for (i = 0, len = shortArrays.length; i < len; i++) {
    // shortArrays[i] is an array of email addresss of 10 or less
}

6

Cách triển khai khác:

const arr = ["H", "o", "w", " ", "t", "o", " ", "s", "p", "l", "i", "t", " ", "a", " ", "l", "o", "n", "g", " ", "a", "r", "r", "a", "y", " ", "i", "n", "t", "o", " ", "s", "m", "a", "l", "l", "e", "r", " ", "a", "r", "r", "a", "y", "s", ",", " ", "w", "i", "t", "h", " ", "J", "a", "v", "a", "S", "c", "r", "i", "p", "t"];

const size = 3; 
const res = arr.reduce((acc, curr, i) => {
  if ( !(i % size)  ) {    // if index is 0 or can be divided by the `size`...
    acc.push(arr.slice(i, i + size));   // ..push a chunk of the original array to the accumulator
  }
  return acc;
}, []);

// => [["H", "o", "w"], [" ", "t", "o"], [" ", "s", "p"], ["l", "i", "t"], [" ", "a", " "], ["l", "o", "n"], ["g", " ", "a"], ["r", "r", "a"], ["y", " ", "i"], ["n", "t", "o"], [" ", "s", "m"], ["a", "l", "l"], ["e", "r", " "], ["a", "r", "r"], ["a", "y", "s"], [",", " ", "w"], ["i", "t", "h"], [" ", "J", "a"], ["v", "a", "S"], ["c", "r", "i"], ["p", "t"]]

NB - Điều này không sửa đổi mảng ban đầu.

Hoặc, nếu bạn thích một phương pháp có chức năng, 100% không thay đổi (mặc dù thực sự không có gì xấu khi đột biến tại chỗ như đã làm ở trên) và phương pháp khép kín:

function splitBy(size, list) {
  return list.reduce((acc, curr, i, self) => {
    if ( !(i % size)  ) {  
      return [
          ...acc,
          self.slice(i, i + size),
        ];
    }
    return acc;
  }, []);
}

5

Để bổ sung cho câu trả lời của @ jyore và trong trường hợp bạn vẫn muốn giữ mảng ban đầu:

var originalArray = [1,2,3,4,5,6,7,8];

var splitArray = function (arr, size) {

  var arr2 = arr.slice(0),
      arrays = [];

  while (arr2.length > 0) {
      arrays.push(arr2.splice(0, size));
  }

  return arrays;
}

splitArray(originalArray, 2);
// originalArray is still = [1,2,3,4,5,6,7,8];

5

Array.reduce có thể không hiệu quả đối với các mảng lớn, đặc biệt là với toán tử mod. Tôi nghĩ rằng một giải pháp chức năng gọn gàng hơn (và có thể dễ đọc hơn) sẽ là:

const chunkArray = (arr, size) =>
  arr.length > size
    ? [arr.slice(0, size), ...chunkArray(arr.slice(size), size)]
    : [arr];

3

Một phương pháp khác:

var longArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var size = 2;

var newArray = new Array(Math.ceil(longArray.length / size)).fill("")
    .map(function() { return this.splice(0, size) }, longArray.slice());

// newArray = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]];

Điều này không ảnh hưởng đến mảng ban đầu như một bản sao, được tạo bằng cách sử dụng lát cắt, được chuyển vào đối số 'this' của bản đồ.


3

Tôi cũng muốn chia sẻ giải pháp của mình. Nó dài dòng hơn một chút nhưng cũng hoạt động tốt.

var data = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];

var chunksize = 4;


var chunks = [];

data.forEach((item)=>{
  if(!chunks.length || chunks[chunks.length-1].length == chunksize)
  chunks.push([]);

  chunks[chunks.length-1].push(item);
});

console.log(chunks);

Đầu ra (đã định dạng):

[ [ 1,  2,  3,  4],
  [ 5,  6,  7,  8],
  [ 9, 10, 11, 12],
  [13, 14, 15    ] ]

2

Một cách triển khai khác, sử dụng Array.reduce (tôi nghĩ rằng nó là cái duy nhất còn thiếu!):

const splitArray = (arr, size) =>
{
    if (size === 0) {
        return [];
    }

    return arr.reduce((split, element, index) => {
        index % size === 0 ? split.push([element]) : split[Math.floor(index / size)].push(element);
        return split;
    }, []);
};

Như nhiều giải pháp ở trên, đây là giải pháp không phá hủy. Trả về một mảng trống khi kích thước bằng 0 chỉ là một quy ước. Nếu ifkhối bị bỏ qua, bạn sẽ gặp lỗi, đó có thể là lỗi bạn muốn.


1

Bạn có thể xem qua mã này. Đơn giản và hiệu quả.

function chunkArrayInGroups(array, unit) {
var results = [],
length = Math.ceil(array.length / unit);

for (var i = 0; i < length; i++) {
    results.push(array.slice(i * unit, (i + 1) * unit));
}
 return results;
}

chunkArrayInGroups(["a", "b", "c", "d"], 2);

1

Đây là một lớp lót đơn giản

var segment = (arr, n) => arr.reduce((r,e,i) => i%n ? (r[r.length-1].push(e), r)
                                                    : (r.push([e]), r), []),
        arr = Array.from({length: 31}).map((_,i) => i+1);
console.log(segment(arr,7));


1

Nhỏ gọn hơn:

const chunk = (xs, size) =>
  xs.map((_, i) =>
    (i % size === 0 ? xs.slice(i, i + size) : null)).filter(Boolean);
    
// Usage:
const sampleArray = new Array(33).fill(undefined).map((_, i) => i);

console.log(chunk(sampleArray, 5));


0

Nếu bạn muốn một phương thức không sửa đổi mảng hiện có, hãy thử cách này:

let oldArray = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
let newArray = [];
let size = 3; // Size of chunks you are after
let j = 0; // This helps us keep track of the child arrays

for (var i = 0; i < oldArray.length; i++) {
  if (i % size === 0) {
    j++
  }
  if(!newArray[j]) newArray[j] = [];
  newArray[j].push(oldArray[i])
}

0
function chunkArrayInGroups(arr, size) {
    var newArr=[];

    for (var i=0; arr.length>size; i++){
    newArr.push(arr.splice(0,size));
    }
    newArr.push(arr.slice(0));
    return newArr;

}

chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6], 3);

dont quên để thực hiện: newArr = [] một biến địa phương
zgthompson

Câu trả lời chỉ có mã có xu hướng bị gắn cờ và sau đó bị xóa vì có Chất lượng thấp. Bạn có thể cung cấp một số bình luận về cách điều này giải quyết vấn đề ban đầu?
Graham

điều này không hoạt động nếu kích thước đoạn nhỏ hơn kích thước mảng đầu vào.
r3wt

0
function chunkArrayInGroups(arr, size) {
    var newArr=[];

    for (var i=0; i < arr.length; i+= size){
    newArr.push(arr.slice(i,i+size));
    }
    return newArr;

}

chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6], 3);

2
Chào mừng bạn đến với stackoverflow. Câu trả lời của bạn sẽ được cải thiện bằng cách thêm một số giải thích.
Simon.SA

0

như một chức năng

var arrayChunk = function (array, chunkSize) {
            var arrayOfArrays = [];

            if (array.length <= chunkSize) {
                arrayOfArrays.push(array);
            } else {
                for (var i=0; i<array.length; i+=chunkSize) {
                    arrayOfArrays.push(array.slice(i,i+chunkSize));
                }
            }
            return arrayOfArrays;
        }

sử dụng

arrayChunk(originalArray, 10) //10 being the chunk size.

0

sử dụng đệ quy

let myArr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
let size = 4; //Math.sqrt(myArr.length); --> For a n x n matrix
let tempArr = [];
function createMatrix(arr, i) {
    if (arr.length !== 0) {
      if(i % size == 0) {
        tempArr.push(arr.splice(0,size))
      } 
      createMatrix(arr, i - 1)
    }
}
createMatrix(myArr, myArr.length);
console.log(tempArr);

Lưu ý: Mảng hiện có tức là myArr sẽ được sửa đổi.


0

bằng cách sử dụng nguyên mẫu, chúng ta có thể đặt trực tiếp thành lớp mảng

Array.prototype.chunk = function(n) {
  if (!this.length) {
    return [];
  }
  return [this.slice(0, n)].concat(this.slice(n).chunk(n));
};
console.log([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15].chunk(5));


0
const originalArr = [1,2,3,4,5,6,7,8,9,10,11];
const splittedArray = [];
  while (originalArr.length > 0) {
    splittedArray.push(originalArr.splice(0,range));  
  }

đầu ra cho phạm vi 3

splittedArray === [[1,2,3][4,5,6][7,8,9][10,11]]

đầu ra cho phạm vi 4

splittedArray === [[1,2,3,4][5,6,7,8][9,10,11]]

Bạn có thể vui lòng thêm một số mô tả?
ego
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.