Я думаю, что это было бы просто, к сожалению, это не так.
Я пытаюсь создать функцию, чтобы взять итеративный из словарей (то есть, список уникальных словарей) и вернуть список списков.уникальных групп словарей.
Если у меня есть 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}]
Так что я ожидаю, что вывод будет выглядетькак их список (где k = 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} )
),
# Team assignment grouping 2
(
# Team 1
( {'name': 'Patricia', 'skill': 4}, {'name': 'Bianca', 'skill': 4} ),
# Team 2
( {'name': 'Nicholas', 'skill': 7}, {'name': 'Christopher', 'skill': 6} )
),
...,
# More unique lists
)
В каждой группе командных назначений должны быть уникальные игроки в разных командах (т. е. в нескольких командах не может быть одного и того же игрока).групповое назначение команд), и каждая групповая группа командных заданий должна быть уникальной.
Как только у меня будет список комбинаций командных назначений, я подытожу навыки в каждой группе, возьму разницу между самым высоким навыком и самым низким навыком.и выберите группировку (с дисперсией) с наименьшей разницей между наивысшими и наименьшими навыками.
Я признаю, что не полностью понимаю этот код.Я понимаю первое назначение, чтобы создать список всех комбинаций букв в строке, и оператор возврата, чтобы найти продукт при условии, что продукт не содержит одну и ту же букву в разных группах.
Моя первоначальная попытка состояла в том, чтобы просто взять it.product(it.combinations(iterable, n), repeat=k)
, но это не позволяет достичь уникальности в разных группах (то есть я получаю одного и того же игрока в разных командах в одной группе).
Заранее спасибо, и с Рождеством!
Обновление:
После значительного беспокойства я получил адаптацию к этому:
Это не работает
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(list({v['name']:v for v in it.chain.from_iterable(i)}.values())) ==\
len(list([x for x in it.chain.from_iterable(i)])))
Я получаю ошибку
Traceback (most recent call last):
File "./optimize.py", line 65, in <module>
for grouping in unique_group(players, team_size, number_of_teams):
File "./optimize.py", line 32, in <genexpr>
v in it.chain.from_iterable(i)})) == len(list([x for x in
File "./optimize.py", line 32, in <dictcomp>
v in it.chain.from_iterable(i)})) == len(list([x for x in
TypeError: tuple indices must be integers or slices, not str
Это сбивает меня с толку и дает понять, что я не знаю, что делает мой код.В ipython я взял этот пример вывода:
assignment = (
({'name': 'Patricia', 'skill': 4}, {'name': 'Bianca', 'skill': 4}),
({'name': 'Patricia', 'skill': 4}, {'name': 'Bianca', 'skill': 4})
)
, что явно нежелательно, и сформулировал следующий тест:
len(list({v['name']:v for v in it.chain.from_iterable(assignment)})) == len([v for v in it.chain.from_iterable(assignment)])
, который правильно отвечает False
.Но это не работает в моем методе.Вероятно, это потому, что я сейчас занимаюсь кодированием грузового культа.
Я понимаю, что делает it.chain.from_iterable(i)
(это сводит кортеж кортежей словарей в просто кортеж словарей).Но кажется, что синтаксис {v['name']:v for v in ...}
делает , а не делает то, что я думаю;либо это, либо я распаковываю неправильные значения!Я пытаюсь проверить уникальные словари по общим словарям на основе Сгладить список списков и Python - Список уникальных словарей , но ответ дает мне
>>> L=[
... {'id':1,'name':'john', 'age':34},
... {'id':1,'name':'john', 'age':34},
... {'id':2,'name':'hanna', 'age':30},
... ]
>>> list({v['id']:v for v in L}.values())
Не так легко адаптироваться в этих обстоятельствах, как я думал, и я понимаю, что на самом деле не знаю, что возвращается в it.product(groups, repeat=k)
.Мне придется больше расследовать.