为了账号安全,请及时绑定邮箱和手机立即绑定

字典集的所有组合成 K 个 N 大小的组

字典集的所有组合成 K 个 N 大小的组

阿晨1998 2021-09-25 14:42:38
我虽然这很简单,但不幸的是,事实并非如此。我正在尝试构建一个函数来获取可迭代的字典(即唯一字典列表)并返回字典唯一分组列表的列表。如果我有x球员,我想组建规模k较大的团队n。这个问题和来自 CMSDK 的一组答案是我能找到的最接近解决方案的东西。在从处理字母字符串到字典的过程中,我发现我的 Python 技能不足。我正在改编的原始函数来自第二个答案:import itertools as itdef unique_group(iterable, k, n):    """Return an iterator, comprising groups of size `k` with combinations of size `n`."""    # Build separate combinations of `n` characters    groups = ("".join(i) for i in it.combinations(iterable, n))    # 'AB', 'AC', 'AD', ...    # Build unique groups of `k` by keeping the longest sets of characters    return (i for i in it.product(groups, repeat=k)                 if len(set("".join(i))) == sum((map(len, i))))     # ('AB', 'CD'), ('AB', 'CE'), ... 我目前的改编(TypeError: object of type 'generator' has no len()由于调用,完全失败并出现错误map(len, i)):def unique_group(iterable, k, n):    groups = []    groups.append((i for i in it.combinations(iterable, n)))    return ( i for i in it.product(groups, repeat=k) if len(set(i)) == sum((map(len, i))) )对于一些上下文:我试图根据他们的技能以编程方式将一组玩家划分为圣诞节琐事的团队。字典列表由一个 yaml 文件组成,看起来像- name: Patricia  skill: 4- name: Christopher  skill: 6- name: Nicholas  skill: 7- name: Bianca  skill: 4其中,在yaml.load生成字典列表之后:players = [{'name':'Patricia', 'skill':4},{'name':'Christopher','skill':6},           {'name':'Nicholas','skill':7},{'name':'Bianca','skill':4}]所以我希望输出看起来像这些( wherek = 2和n = 2)的列表:(    # Team assignment grouping 1    (        # Team 1        ( {'name': 'Patricia', 'skill': 4}, {'name': 'Christopher', 'skill': 6} ),        # Team 2        ( {'name': 'Nicholas', 'skill': 7}, {'name': 'Bianca', 'skill': 4} )    ),)每个团队分配分组需要在团队中具有唯一的球员(即,团队分配分组中的多个团队中不能有相同的球员),并且每个团队分配分组都需要是唯一的。一旦我有了团队分配组合列表,我将总结每个组的技能,取最高技能和最低技能之间的差异,并选择最高技能和最低技能之间差异最小的分组(有方差)。我承认我不完全理解这段代码。我理解第一个任务是创建一个字符串中所有字母组合的列表,以及在产品不包含不同组中相同字母的情况下查找产品的返回语句。我最初的尝试是简单地采用 ,it.product(it.combinations(iterable, n), repeat=k)但这并不能实现跨组的唯一性(即,我在一个分组的不同团队中获得相同的球员)。
查看完整描述

6 回答

?
慕桂英4014372

TA贡献1871条经验 获得超13个赞

这是我利用集合的新数据类的地方。您可以通过frozen=True在装饰器中设置来使数据类可散列。首先,您要将玩家添加到一个集合中以获得独特的玩家。然后你会得到 n 大小球队的所有球员组合。然后你可以创建一组独特的团队。然后创建有效的分组,而没有球员在团队中出现多次。最后,您可以计算整个分组的总团队技能水平的最大差异(再次利用组合),并使用它来对您的有效分组进行排序。所以像这样的事情。


from dataclasses import dataclass

from itertools import combinations

from typing import FrozenSet


import yaml



@dataclass(order=True, frozen=True)

class Player:

    name: str

    skill: int



@dataclass(order=True, frozen=True)

class Team:

    members: FrozenSet[Player]


    def total_skill(self):

        return sum(p.skill for p in self.members)



def is_valid(grouping):

    players = set()

    for team in grouping:

        for player in team.members:

            if player in players:

                return False

            players.add(player)

    return True



def max_team_disparity(grouping):

    return max(

        abs(t1.total_skill() - t2.total_skill())

        for t1, t2 in combinations(grouping, 2)

    )



def best_team_matchups(player_file, k, n):

    with open(player_file) as f:

        players = set(Player(p['name'], p['skill']) for p in yaml.load(f))

    player_combs = combinations(players, n)

    unique_teams = set(Team(frozenset(team)) for team in player_combs)

    valid_groupings = set(g for g in combinations(unique_teams, k) if is_valid(g))

    for g in sorted(valid_groupings, key=max_team_disparity):

        print(g)



best_team_matchups('test.yaml', k=2, n=4)

示例输出:


(

    Team(members=frozenset({

        Player(name='Chr', skill=6),

        Player(name='Christopher', skill=6),

        Player(name='Nicholas', skill=7),

        Player(name='Patricia', skill=4)

    })),

    Team(members=frozenset({

        Player(name='Bia', skill=4),

        Player(name='Bianca', skill=4),

        Player(name='Danny', skill=8),

        Player(name='Nicho', skill=7)

    }))

)


查看完整回答
反对 回复 2021-09-25
  • 6 回答
  • 0 关注
  • 210 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号