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

我虽然这很简单,但不幸的是,事实并非如此。


我正在尝试构建一个函数来获取可迭代的字典(即唯一字典列表)并返回字典唯一分组列表的列表。


如果我有x球员,我想组建规模k较大的团队n。

这个问题和来自 CMSDK 的一组答案是我能找到的最接近解决方案的东西。在从处理字母字符串到字典的过程中,我发现我的 Python 技能不足。


我正在改编的原始函数来自第二个答案:


import itertools as it

def 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)但这并不能实现跨组的唯一性(即,我在一个分组的不同团队中获得相同的球员)。


阿晨1998
浏览 211回答 6
6回答

慕桂英4014372

这是我利用集合的新数据类的地方。您可以通过frozen=True在装饰器中设置来使数据类可散列。首先,您要将玩家添加到一个集合中以获得独特的玩家。然后你会得到 n 大小球队的所有球员组合。然后你可以创建一组独特的团队。然后创建有效的分组,而没有球员在团队中出现多次。最后,您可以计算整个分组的总团队技能水平的最大差异(再次利用组合),并使用它来对您的有效分组进行排序。所以像这样的事情。from dataclasses import dataclassfrom itertools import combinationsfrom typing import FrozenSetimport 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 Truedef 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)    })))
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python