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

基于年龄与性别将n人划分为m个均衡子组及实现shuffle功能的算法咨询

均衡分组与保持均衡的随机置换算法方案

前置合法性校验

分组前先做基础校验,判断当前人员池是否支持符合要求的划分:

  • 将所有人按「出生年份+性别」做独立分层,统计每个分层的总人数
  • 若要求所有子组必须包含全部年份+性别组合,需保证每个分层的总人数≥m;若允许部分子组缺少个别分层(如示例中1982年男性仅2人,第3组无该分层人员),则无强制要求,最终各子组同一分层的人数差不会超过1。

核心分组算法:分层随机均摊法

该算法完全匹配你的需求,逻辑简单且性能高:

  1. 对每个「出生年份+性别」的独立分层,先将该分层下的人员列表做随机打乱
  2. 按顺序把打乱后的列表循环均摊分配到m个组中:比如某分层共6人分3组,每组分配2人;某分层共2人分3组,前2组各分配1人,第3组分配0人。
    该方式天然保证每个子组内同出生年份人数一致、同年龄层男女比例完全相同,你的示例输出完全符合该算法的分配结果。

保持均衡的随机置换函数实现

要实现随机调换人员且不破坏分组均衡,核心规则是仅能在同一个「出生年份+性别」分层内做跨组交换,绝对不允许跨分层交换人员,实现步骤如下:

  1. 提前为每个分层维护「各组成员列表」的映射关系
  2. 每次置换时,随机选择1个分层,再随机选择2个拥有该分层人员的不同子组,从两个子组的该分层人员中各随机选1人做交换
  3. 批量置换时重复上述操作指定次数即可,无论交换多少次都不会破坏各分层的人数分布,自然不会打破子组的年份人数、男女比例均衡。

参考伪代码

from collections import defaultdict
import random

# 均衡分组函数
def split_to_balanced_groups(people, group_num):
    # 按出生年份+性别聚合分层
    layer_map = defaultdict(list)
    for person in people:
        layer_key = (person["birth_year"], person["gender"])
        layer_map[layer_key].append(person)
    # 初始化空分组
    groups = [[] for _ in range(group_num)]
    for layer_key, person_list in layer_map.items():
        # 分层内先随机打乱
        random.shuffle(person_list)
        # 循环均摊到各个组
        for idx, person in enumerate(person_list):
            groups[idx % group_num].append(person)
    return groups, layer_map

# 保持均衡的shuffle函数
def balanced_shuffle(groups, layer_map, swap_times=100):
    group_num = len(groups)
    # 构建分层的组内成员索引
    layer_group_index = defaultdict(lambda: [[] for _ in range(group_num)])
    for g_idx, group in enumerate(groups):
        for person in group:
            layer_key = (person["birth_year"], person["gender"])
            layer_group_index[layer_key][g_idx].append(person)
    # 执行指定次数交换
    for _ in range(swap_times):
        # 随机选一个有至少2个组存在成员的分层
        layer_key = random.choice(list(layer_group_index.keys()))
        group_member_lists = layer_group_index[layer_key]
        valid_group_idx = [i for i in range(group_num) if len(group_member_lists[i]) > 0]
        if len(valid_group_idx) < 2:
            continue
        # 选两个不同的组,各挑1人交换
        g1, g2 = random.sample(valid_group_idx, 2)
        p1 = random.choice(group_member_lists[g1])
        p2 = random.choice(group_member_lists[g2])
        # 更新分组列表
        groups[g1].remove(p1)
        groups[g1].append(p2)
        groups[g2].remove(p2)
        groups[g2].append(p1)
        # 更新分层索引
        group_member_lists[g1].remove(p1)
        group_member_lists[g1].append(p2)
        group_member_lists[g2].remove(p2)
        group_member_lists[g2].append(p1)
    return groups

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 12:57:02