JavaScript如何将对象中的多类数组元素按每组n个均等分组
水果分盒问题解决方案
实现思路
- 优先统计所有水果总数量,若总数量≤单盒最大容量n,直接返回1个装全量水果的盒子即可
- 为每类水果创建独立的拷贝队列,避免分配操作修改原始数据
- 采用轮询取果逻辑:按固定顺序循环从仍有剩余的水果队列中取1个放入当前盒子,盒子装满n个就存入结果并开启新盒子
- 该取法天然保证不同品类水果尽可能均匀分布,不会出现单类水果集中在少数盒子的问题
完整代码实现
无依赖原生JS版本
function distributeFruits(fruitBox, n) { // 拷贝每类水果生成独立队列,不修改原始数据 const fruitQueues = Object.values(fruitBox).map(list => [...list]); // 统计总水果数 const totalFruitCount = fruitQueues.reduce((sum, queue) => sum + queue.length, 0); // 总数量小于等于单盒容量,直接返回一个盒子 if (totalFruitCount <= n) { return [fruitQueues.flat()]; } const resultBoxes = []; let currentBox = []; let typeIndex = 0; const totalTypeCount = fruitQueues.length; // 循环直到所有水果分配完成 while (fruitQueues.some(queue => queue.length > 0)) { const currentTypeQueue = fruitQueues[typeIndex]; // 当前品类还有剩余则取一个放入当前盒子 if (currentTypeQueue.length > 0) { currentBox.push(currentTypeQueue.shift()); // 当前盒子装满则存入结果,开启新盒子 if (currentBox.length === n) { resultBoxes.push(currentBox); currentBox = []; } } // 轮询到下一个品类 typeIndex = (typeIndex + 1) % totalTypeCount; } // 存入最后一个未装满的盒子(如果有) if (currentBox.length > 0) { resultBoxes.push(currentBox); } return resultBoxes; }
测试用例(匹配题目示例)
const boxOfFruits = { apples: [ { name: "Kashmiri" }, { name: "Washington" }, { name: "Himalayan" }, { name: "Fuji" } ], oranges: [ { name: "Nagpur" }, { name: "Clementine" } ], mangoes: [ { name: "Totapuri" }, { name: "Alphonso" }, { name: "Langda" } ] }; // 单盒最多放3个 const distributedBoxes = distributeFruits(boxOfFruits, 3); console.log(distributedBoxes); /* 输出结果完全符合预期: [ [ {name: 'Kashmiri'}, {name: 'Nagpur'}, {name: 'Totapuri'} ], [ {name: 'Washington'}, {name: 'Clementine'}, {name: 'Alphonso'} ], [ {name: 'Himalayan'}, {name: 'Langda'}, {name: 'Fuji'} ] ] */
Lodash 简化版本
如果你已经在项目中使用Lodash,可以用以下简化实现:
const _ = require('lodash'); function distributeFruitsLodash(fruitBox, n) { const fruitQueues = _.mapValues(fruitBox, list => [...list]); const fruitTypes = _.keys(fruitQueues); const totalFruitCount = _.sumBy(fruitTypes, type => fruitQueues[type].length); if (totalFruitCount <= n) return [_.flatten(_.values(fruitQueues))]; const resultBoxes = []; let currentBox = []; let typeIndex = 0; const totalTypeCount = fruitTypes.length; while (_.some(fruitTypes, type => fruitQueues[type].length > 0)) { const currentType = fruitTypes[typeIndex]; if (fruitQueues[currentType].length) { currentBox.push(fruitQueues[currentType].shift()); if (currentBox.length === n) { resultBoxes.push(currentBox); currentBox = []; } } typeIndex = (typeIndex + 1) % totalTypeCount; } currentBox.length && resultBoxes.push(currentBox); return resultBoxes; }
方案特性
- 支持动态增减水果品类,无需修改代码,自动识别所有传入对象的键
- 支持任意自定义单盒最大容量n
- 自动兼容总水果数小于n的场景,仅返回1个盒子
- 轮询取果逻辑保证不同品类水果分布尽可能均匀,无扎堆问题
内容的提问来源于stack exchange,提问作者Vaulstein
相关产品推荐
相关产品推荐

