实现lodash的chunk方法--数组按指定长度拆分

手写实现lodash库中的chunk方法,将数组按照指定长度拆分成多个子数组

问题

实现一个 chunk 函数,将一个数组按照指定的长度拆分成多个子数组。如果数组无法被平均分割,最后一个子数组将包含剩余的元素。

例如:chunk([1, 2, 3, 4, 5], 2) 应该返回 [[1, 2], [3, 4], [5]]

解答

/**
 * 将数组按指定长度拆分成多个子数组
 * @param {Array} array - 需要处理的数组
 * @param {number} size - 每个子数组的长度
 * @returns {Array} 返回拆分后的二维数组
 */
function chunk(array, size = 1) {
  // 参数校验
  if (!Array.isArray(array)) {
    return [];
  }
  
  // size 必须是大于 0 的整数
  if (size < 1 || !Number.isInteger(size)) {
    return [];
  }
  
  const result = [];
  
  // 方法一:使用 for 循环和 slice
  for (let i = 0; i < array.length; i += size) {
    result.push(array.slice(i, i + size));
  }
  
  return result;
}

// 方法二:使用 while 循环
function chunk2(array, size = 1) {
  if (!Array.isArray(array) || size < 1 || !Number.isInteger(size)) {
    return [];
  }
  
  const result = [];
  let index = 0;
  
  while (index < array.length) {
    result.push(array.slice(index, index + size));
    index += size;
  }
  
  return result;
}

// 方法三:使用 reduce
function chunk3(array, size = 1) {
  if (!Array.isArray(array) || size < 1 || !Number.isInteger(size)) {
    return [];
  }
  
  return array.reduce((result, item, index) => {
    // 每 size 个元素创建一个新的子数组
    if (index % size === 0) {
      result.push([item]);
    } else {
      // 将元素添加到最后一个子数组
      result[result.length - 1].push(item);
    }
    return result;
  }, []);
}

使用示例

// 基本使用
console.log(chunk([1, 2, 3, 4, 5], 2));
// 输出: [[1, 2], [3, 4], [5]]

console.log(chunk([1, 2, 3, 4, 5, 6], 3));
// 输出: [[1, 2, 3], [4, 5, 6]]

console.log(chunk([1, 2, 3, 4, 5], 1));
// 输出: [[1], [2], [3], [4], [5]]

// 边界情况
console.log(chunk([], 2));
// 输出: []

console.log(chunk([1, 2, 3], 5));
// 输出: [[1, 2, 3]]

console.log(chunk([1, 2, 3, 4], 0));
// 输出: []

console.log(chunk([1, 2, 3, 4]));
// 输出: [[1], [2], [3], [4]] (默认 size 为 1)

// 处理字符串数组
console.log(chunk(['a', 'b', 'c', 'd', 'e'], 2));
// 输出: [['a', 'b'], ['c', 'd'], ['e']]

// 处理对象数组
const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' },
  { id: 3, name: 'Charlie' },
  { id: 4, name: 'David' }
];
console.log(chunk(users, 2));
// 输出: [[{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }], 
//       [{ id: 3, name: 'Charlie' }, { id: 4, name: 'David' }]]

关键点

  • 参数校验:需要验证输入是否为数组,size 是否为大于 0 的整数
  • 默认参数:size 默认值设为 1,符合 lodash 的行为
  • slice 方法:使用 array.slice(start, end) 来截取子数组,不会修改原数组
  • 循环步长:每次循环递增 size,确保不重复不遗漏
  • 边界处理:当数组长度不能被 size 整除时,最后一个子数组自动包含剩余元素
  • 性能考虑:方法一(for + slice)性能最优,代码简洁易懂,推荐使用
  • 不可变性:所有方法都不会修改原数组,返回新的二维数组