5 cách chia một mảng lớn thành nhiều mảng nhỏ trong Javascript

3911

Dạo này hay xử lý mảng bằng JS nên sẵn viết để chia sẻ vài tips nhỏ, bài này chia sẻ việc chia nhỏ một mảng thành các mảng nhỏ hơn bằng nhiều cách khác nhau.

1.Dùng vòng lặp For và hàm slice

Về cơ bản, mọi phương pháp đều dùng phương thức slice để cắt nhỏ mảng, trong trường hợp này là phương thức dùng vòng lặp For.

Trong trường hợp mảng  không đồng nhất thì các item còn lại cũng sẽ nằm trong một mảng nhỏ, mảng nhỏ này tất nhiên sẽ có ít item hơn mấy mảng trước. Thôi làm cái ví dụ cho dễ hiểu nghen, ta có 1 mảng có 8 item, chia làm 3 mảng nhỏ hơn thì output ra sao ta:

function chunkArray(myArray, chunk_size){
    var index = 0;
    var arrayLength = myArray.length;
    var tempArray = [];

    for (index = 0; index < arrayLength; index += chunk_size) {
        myChunk = myArray.slice(index, index+chunk_size);
        // Do something if you want with the group
        tempArray.push(myChunk);
    }

    return tempArray;
}
// chia moi group co 3 item
var result = chunkArray([1,2,3,4,5,6,7,8], 3);
// Outputs : [ [1,2,3] , [4,5,6] ,[7,8] ]
console.log(result);

2.Sử dụng một vòng lặp For, slice và thiết lập function trong prototype của array

Rồi, prototype của array là cái quỷ gì? Trong Javascript nó không có khái niệm Class nha các bợn (ơ kì >_<) nên để kế thừa các trường hay hàm của object thì phải sử dụng prototype nghen anh em. Vì vậy nói ngắn gọn lại là prototype của object là cha của nó.

Cách hai này là chúng ta tạo nhiều hàm tùy chỉnh trong prototype của hàm, trong trường hợp này ta tạo một hàm mang tên là chunk để quất nó:

/**
 * Dinh nghia phuong thuc cua khoi (chunk) trong prototype cua mot array
 * sau do tra ve ket qua la nhung mang nho hon voi cac item da quy dinh.
 *
 * @param chunkSize {Integer} so luong item trong tung group
 */
Object.defineProperty(Array.prototype, 'chunk', {
    value: function(chunkSize){
        var temporal = [];

        for (var i = 0; i < this.length; i+= chunkSize){
            temporal.push(this.slice(i,i+chunkSize));
        }

        return temporal;
    }
});
// chia moi group co 3 item
var result = [1,2,3,4,5,6,7,8].chunk(3);
// Outputs : [ [1,2,3] , [4,5,6] ,[7,8] ]
console.log(result);

Như bạn thấy, nguyên tắc giống nhau là sử dụng một vòng lặp for và phương thức slice nhưng thay vì sử dụng nó trong một hàm, chúng ta quy định nó trong một prototype của mảng. Thì giống như 1 bài toán có nhiều cách giải thôi, thích cách nào thì làm cách đó, vậy đi!

3.Sử dụng array map trong prototype của mảng.

Object.defineProperty(Array.prototype, 'chunk', {
    value: function(chunkSize) {
        var that = this;
        return Array(Math.ceil(that.length/chunkSize)).fill().map(function(_,i){
            return that.slice(i*chunkSize,i*chunkSize+chunkSize);
        });
    }
});

var result = [1,2,3,4,5,6,7,8].chunk(3);
// Outputs : [ [1,2,3] , [4,5,6] ,[7,8] ]
console.log(result);

 4.Sử dụng vòng lặp while và slice

Trong điều kiện bình thường thì vòng lặp while có hiệu suất nhanh hơn một chút so với các phương thức khác, đây là điều chúng ta cũng nên lưu ý về mặt hiệu suất vì khi gặp số lần lặp lớn chẳng hạn, mỗi thứ nhanh một chút cộng lại sẽ nhanh hơn nhiều lần. Vì vậy nếu mảng của bạn rất lớn và bạn muốn băm rất nhỏ thì nên cân nhắc dùng vòng lặp while để tăng performance nghen, kinh nghiệm cá nhân thoai nên ai ko nghe cũng dc.

function chunkArray(myArray, chunk_size){
    var results = [];

    while (myArray.length) {
        results.push(myArray.splice(0, chunk_size));
    }

    return results;
}

var result = chunkArray([1,2,3,4,5,6,7,8], 3);
// Outputs : [ [1,2,3] , [4,5,6] ,[7,8] ]
console.log(result);

 5.Về performance của từng cách

Rồi bây giờ thử benchmark bằng cách băm 1 mảng có 100.000 item (là con số thôi), chia thành khối nhỏ chứa 3 item thôi.

Phương thức Tổng time (ms) Thời gian trung bình cho 1 task (ms)
1 (for loop) 5778.015000000001 5.776805000000013
2 (for loop in prototype) 5681.145 5.679875000000007
3 (array map in prototype) 8855.470000000001 8.854190000000001
4 (while loop) 1468.6650000000002 1.468275000000002

Rồi xem bản chỉ số thì thấy dùng vòng lặp while chạy ngon hơn nghen, nên ngon thì dùng thôi. Cám ơn các bạn đã đọc, hy vọng sẽ giúp đỡ được ai đó!

  Thấu hiểu các JavaScript Closure: Phương pháp tiếp cận thực tiễn