如何在Google Apps Script中按特定条件分配数组
Google Apps Script 数组分组分配实现方案
需求概述
现有三类数组需按规则完成分配:
- 人员数组:
var array1 = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18] - 日期数组:
var array2 = ["date1","date2","date3","date4"] - 日期分组数组:每个日期对应一组分组,例如
date1Groups = [[1,6,7,8],[4,5,9],[6,17,15,3,11]],其余日期对应date2Groups、date3Groups、date4Groups
分配规则:
- 按日期数量比例分配人员:示例中18人分4组,需生成2个含5元素、2个含4元素的数组
- 单个日期的结果数组中,任意两个元素不能同时出现在该日期的任一分组内(如6和8同属date1的一个分组,则不能同时出现在date1的结果数组中)
实现步骤与代码
完整代码实现
function allocatePersonnel() { // 原始数据 const array1 = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18]; const dateList = ["date1","date2","date3","date4"]; // 日期分组映射,统一管理各日期的分组数据 const dateGroupsMap = { date1: [[1,6,7,8],[4,5,9],[6,17,15,3,11]], date2: [[2,10,12],[3,13,16],[7,14,18]], // 示例分组,可替换为实际数据 date3: [[5,11,15],[8,17,1],[4,12,16]], // 示例分组,可替换为实际数据 date4: [[9,10,13],[2,6,14],[3,7,18]] // 示例分组,可替换为实际数据 }; // 为每个日期构建冲突映射表:快速查询某人员的所有冲突对象 const conflictMap = {}; dateList.forEach(date => { conflictMap[date] = new Map(); const groups = dateGroupsMap[date]; groups.forEach(group => { group.forEach(person => { const conflicts = new Set(group.filter(p => p !== person)); conflictMap[date].set(person, conflicts); }); }); }); // 计算每个日期应分配的人数 const totalPersons = array1.length; const dateCount = dateList.length; const baseCount = Math.floor(totalPersons / dateCount); const extraCount = totalPersons % dateCount; const targetCounts = dateList.map((_, index) => index < extraCount ? baseCount + 1 : baseCount); // 初始化结果数组,先分配前dateCount个人员到各数组 const resultArrays = dateList.map((_, index) => [array1[index]]); const remainingPersons = array1.slice(dateCount); // 遍历剩余人员,逐个分配到符合条件的数组 remainingPersons.forEach(person => { for (let i = 0; i < resultArrays.length; i++) { const currentArray = resultArrays[i]; const date = dateList[i]; let canAdd = true; // 检查当前人员与数组中已有元素是否冲突 for (const p of currentArray) { if (conflictMap[date].has(p) && conflictMap[date].get(p).has(person)) { canAdd = false; break; } } // 符合条件则加入数组 if (canAdd && currentArray.length < targetCounts[i]) { currentArray.push(person); break; } } }); // 输出结果,可按需调整格式 console.log("分配结果:"); dateList.forEach((date, index) => { console.log(`${date}:`, resultArrays[index]); }); return resultArrays; }
关键逻辑说明
- 冲突映射表:将每个日期的分组转换为
Map结构,键为人员ID,值为该人员的所有冲突人员集合,避免重复遍历原始分组,提升检查效率 - 人数分配逻辑:通过取整和取余计算每个日期的目标人数,保证分配比例符合总人数与日期数量的对应关系
- 人员分配逻辑:遍历剩余人员,对每个人员依次检查各日期的结果数组,找到第一个无冲突且未达人数上限的数组加入,确保分配过程完全符合规则
内容的提问来源于stack exchange,提问作者Sergio Delgado
相关产品推荐
相关产品推荐

