You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JavaScript/TypeScript中实现人员向活动的均匀分配

人员均等分配活动的 TypeScript/JavaScript 实现

实现思路

  • 先统计所有活动的总需求人次,结合总人数计算出每人的基准参与次数,若总人次无法被人数整除,余数部分会分配给对应数量的人员多参与1次,保证所有人参与次数的差距最大不超过1次
  • 维护每个人员的参与次数、已参与活动记录,分配单个活动名额时,优先选择当前参与次数最少、且未报名过本次活动的人员
  • 按活动顺序逐批完成分配,所有活动都能保证招满所需人数

完整实现代码

// 人员类型定义
type Person = {
  name: string;
  // 已参与活动次数
  participateCount: number;
  // 已参与的活动日期(避免同一个人重复参加同个活动)
  participatedActivities: Set<string>;
}

// 活动类型定义
type Activity = {
  date: string;
  required: number;
  // 已分配的人员名单
  assigned: string[];
}

/**
 * 人员分配核心方法
 * @param personNames 所有参与人员的姓名列表
 * @param activities 所有活动的基础信息(日期、所需人数)
 * @returns 完成分配的活动列表
 */
function assignActivities(personNames: string[], activities: Omit<Activity, 'assigned'>[]): Activity[] {
  // 初始化人员基础数据
  const persons: Person[] = personNames.map(name => ({
    name,
    participateCount: 0,
    participatedActivities: new Set()
  }));

  // 逐个活动分配人员
  return activities.map(activity => {
    const currentActivity: Activity = {
      ...activity,
      assigned: []
    };

    // 招满当前活动所需人数为止
    while (currentActivity.assigned.length < activity.required) {
      // 筛选未参加过本次活动的人员,按已参与次数升序排序,优先选参与次数少的
      const availablePersons = persons
        .filter(p => !p.participatedActivities.has(activity.date))
        .sort((a, b) => a.participateCount - b.participateCount);
      
      // 取排序第一的人员分配到本次活动
      const selected = availablePersons[0];
      currentActivity.assigned.push(selected.name);
      selected.participateCount++;
      selected.participatedActivities.add(activity.date);
    }

    return currentActivity;
  });
}

// ------------ 示例调用 ------------
const allPersons = ['John', 'Jack', 'Harry', 'Charlie', 'Jacob'];
const allActivities = [
  { date: '10.10.2021', required: 4 },
  { date: '11.10.2021', required: 2 },
  { date: '12.10.2021', required: 1 },
  { date: '13.10.2021', required: 3 },
  { date: '14.10.2021', required: 5 },
];

const assignedResult = assignActivities(allPersons, allActivities);

// 打印分配结果
console.log('活动分配结果:');
assignedResult.forEach(act => {
  console.log(`${act.date}:${act.assigned.join('、')}`);
});

// 统计每人参与次数
const participateCountMap = assignedResult.reduce((map, act) => {
  act.assigned.forEach(name => map[name] = (map[name] || 0) + 1);
  return map;
}, {} as Record<string, number>);
console.log('每人参与次数:', participateCountMap);

如果要改为纯JavaScript实现,只需要删掉所有类型定义即可,逻辑完全通用。

运行示例输出

活动分配结果:
10.10.2021:John、Jack、Harry、Charlie
11.10.2021:Jacob、John
12.10.2021:Jack
13.10.2021:Harry、Charlie、Jacob
14.10.2021:John、Jack、Harry、Charlie、Jacob
每人参与次数: { John: 3, Jack: 3, Harry: 3, Charlie: 3, Jacob: 3 }

内容的提问来源于stack exchange,提问作者Matteo Lutz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 03:54:03