Chia mảng JavaScript thành nhiều phần bằng Lodash


83

Tôi cần chia một mảng JavaScript thành ncác phần có kích thước.

Vd: Cho mảng này

["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13"]

và a nbằng 4, đầu ra phải là:

[ ["a1", "a2", "a3", "a4"],
  ["a5", "a6", "a7", "a8"],
  ["a9", "a10", "a11", "a12"],
  ["a13"]
]

Tôi biết các giải pháp JavaScript thuần túy cho vấn đề này, nhưng vì tôi đã sử dụng Lodash nên tôi đang tự hỏi liệu Lodash có cung cấp giải pháp tốt hơn cho vấn đề này hay không.

Biên tập:

Tôi đã tạo thử nghiệm jsPerf để kiểm tra xem giải pháp gạch dưới chậm hơn bao nhiêu.

Câu trả lời:


125

Xem qua lodash ' chunk : https://lodash.com/docs#chunk

const data = ["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13"];
const chunks = _.chunk(data, 3);
console.log(chunks);
// [
//  ["a1", "a2", "a3"],
//  ["a4", "a5", "a6"],
//  ["a7", "a8", "a9"],
//  ["a10", "a11", "a12"],
//  ["a13"]
// ]
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>


Nó sẽ rất hữu ích nếu lodash và gạch dưới cả hai API tương thích ngược
Jonno_FTW

@Jonah Đúng là như vậy. Câu trả lời trước đó không còn là một trong những tốt nhất, do đó tôi cập nhật các câu trả lời được chấp nhận vì lợi ích của các độc giả :)
Cesar Canassa

90

Đối với giải pháp dựa trên gạch dưới, hãy thử cách này:

var data = ["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13"];
var n = 3;
var lists = _.groupBy(data, function(element, index){
  return Math.floor(index/n);
});
lists = _.toArray(lists); //Added this to convert the returned object to an array.
console.log(lists);

Sử dụng phương thức trình bao bọc chuỗi, bạn có thể kết hợp hai câu lệnh như sau:

var data = ["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13"];
var n = 3;
var lists = _.chain(data).groupBy(function(element, index){
  return Math.floor(index/n);
}).toArray()
.value();

1
Thật kỳ lạ, dấu gạch dưới groupBy trả về một đối tượng , không phải một mảng. Không phải là một công cụ thỏa thuận - về cơ bản bạn sẽ có cùng chức năng - nhưng một chút ngữ nghĩa kỳ lạ. Chỉnh sửa: Ồ, nó làm điều đó để duy trì khả năng chịu đựng. Vẫn thú vị.
Jordan Running

@Cesar Canassa: Vì lợi ích của các nhà phát triển trong tương lai, những người đọc mã đó, vui lòng xem xét đặt nó dưới dạng một hàm trong thư viện tùy chỉnh nếu bạn sẽ sử dụng nó nhiều hoặc nhận xét nó tốt nếu bạn không :)
Briguy37

@Jordan: Không nhận ra điều đó. Đã chỉnh sửa câu trả lời để chuyển đổi đối tượng thành mảng.
Chandu

Trong khi tất cả tôi đều sử dụng Dấu gạch dưới cho những thứ nó hoạt động tốt nhất (và OP đã yêu cầu giải pháp dựa trên Dấu gạch dưới để dấu không bị đánh giá thấp) và cho các giải pháp chức năng, có vẻ như giải pháp này giới thiệu rất nhiều chi phí. Như @ ajax33321 đã chỉ ra, splicetrong một vòng lặp vẫn là ba lớp lót và, tôi đoán, sẽ hoạt động hiệu quả hơn. Nếu mảng của bạn ngắn, điều đó có thể không thành vấn đề, nhưng nếu bạn đang xử lý hàng trăm hoặc hàng nghìn mặt hàng, hãy để ý đến hiệu suất của nó.
Jordan Running

1
Đây không còn là giải pháp tốt nhất. Vui lòng sử dụng chunk () thay thế
Jonah

4

Một biểu thức có thể đơn giản hơn:

const coll = [ "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9" ];
const n = 2;
const chunks = _.range(coll.length / n).map(i => coll.slice(i * n, (i + 1) * n));
console.log(chunks);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>


1
Đơn giản hơn những gì? Câu trả lời nên đứng một mình.
Nathan Tuggy

4

Underscore hỗ trợ _.chunk () nguyên bản kể từ phiên bản 1.9.0.

const data = ["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13"];
const chunks = _.chunk(data, 4);
console.log(chunks);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore.js"></script>


1

hãy thử cái này, nó thực tế hơn nhiều (ví dụ: nếu bạn muốn chia mảng dựa trên số lượng các mục sẽ được chứa trong mỗi mảng con):

function chunk(arr, start, amount){
    var result = [], 
        i, 
        start = start || 0, 
        amount = amount || 500, 
        len = arr.length;

    do {
        //console.log('appending ', start, '-', start + amount, 'of ', len, '.');
        result.push(arr.slice(start, start+amount));
        start += amount;

    } while (start< len);

    return result;
};

và việc sử dụng trong trường hợp của bạn:

var arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17],
    chunked = chunk(arr, 0, Math.floor(arr.length/3)); //to get 4 nested arrays

console.log(chunked);

và một trường hợp khác:

var arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17],
    chunked = chunk(arr, 0, 3); // to get 6 nested arrays each containing maximum of 3 items

console.log(chunked);

startTham số đó không thực sự thực tế imho. Bạn thường không muốn vượt qua nó; nhưng bạn luôn cần chỉ định kích thước chunk. Tốt hơn hãy hoán đổi hai tham số đó.
Bergi

Tại sao đây là một do whilevòng lặp? Không ai muốn nhận được những khối rỗng.
Bergi
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.