Python - 迭代的两个列表中每个列表中的三个项目的组合

时间:2015-11-27 06:43:10

标签: python

另一个编辑: 我想我可能没有说清楚这个问题。每个Person都有一个单独的列表,列出了他们可以执行的任务,并且无法保证Person1始终拥有列表中三个任务中的第一个。我已经尝试了一些在答案中提出的事情,但都没有得到我想要的结果。使用zipdict只检查使用Person个对象的组合,它们与列表中显示的顺序相同,这给了我一堆不正确的答案。使用itertools.combinations解决了这个问题但测试了每一组可能的人 - 任务组合,这再次给了我一些我不想要的组合。

我想要最终实现的是列表bad_options,其中包含通过为每个tasks分配一个task无法涵盖的所有三个person的集合。我不需要每一个排列(例如,如果三个tasks [Task1, Task3, Task6]Person1, Person3, Person2按顺序排列,我不希望[Task1, Task3, Task6]被添加到bad_options。如果这还不够清楚,我会提前道歉;如果此时我应该提出一个新问题,请随意发表评论并说出来并且我会接受路由。

根据以下答案,我尝试过:

for setup in setups:
    combo = dict(zip(setup, people))
    possibilities.append(combo)
for setup in possibilities:
    for task, person in setup.items():
        if not task in person.tasks:
            if not setup in bad_options:
                bad_options.append(setup)
            break
        else:
            pass

这将返回所有可能的任务组合,就好像它们都没有被覆盖一样,即使我直接设置每个person.tasks以确保它们都应该有效且函数不返回任何内容。我现在做错了什么?

我需要结合以下内容:

tasks = ['Task1', 'Task2', 'Task3', 'Task4', 'Task5', ...]
people = [Person1, Person2, Person3]

每个Person是一个类的实例,其中一个属性是人员可以执行的任务列表。我将不得不分配三个总任务,每个人一个。我想确保可用人员可以涵盖三个任务的所有可能组合。

我已经构建了代码,该代码将为我提供三个任务的所有可能组合的列表:

setups = (('Task1', 'Task2', 'Task3'),
          ('Task1', 'Task2', 'Task4'),
          ('Task1', 'Task2', 'Task5'), ...)

(之所以我单独做这个部分,是因为对于哪些任务组合可以组合起来还有限制,我已经编写了一个单独的脚本来消除非法组合。我不希望有复制这种努力,但如果以这种方式这样做可以这样做是愚蠢的。)

我认为我需要在for上使用setups循环,可能使用类似itertools.combinations的内容?我正在寻找结果作为一个dicts列表,如:

options = [['Task1' : Person1, 'Task2' : Person2, 'Task3' : Person3],
           ['Task1' : Person1, 'Task2' : Person2, 'Task4' : Person3], ...]

我迷失了如何获得这个词典列表。我假设列表上的迭代类似于:

for option in options:
    for task, person in option.items():
        if task[0] in person[0].tasks and task[1] in person[1].tasks and task[2] in person[2].tasks:
            True
        else:
            bad_options.append(option)
然后

bad_options会列出未正确涵盖的任务组合(如果有的话),对吗?

底线问题:我如何获得该词典列表,并且我的代码是否正确迭代?或者,我很高兴被告知有更好的方法来实现目标。为了获得额外的功劳,我将来会从确定培训每个人的任务中获益,以便他们能够涵盖所有可能性(但如果不清楚或者你可以回答第一个问题,请忽略它)但不是这个。)

3 个答案:

答案 0 :(得分:1)

不确定,但也许这就是你需要的(如果问题是如何获得dicts列表)

>>> import itertools
>>> tasks = ['Task1', 'Task2', 'Task3', 'Task4', 'Task5']
>>> people = [1, 2, 3]
>>> setups = itertools.combinations(tasks, len(people))
>>> options = [{task: person for task, person in zip(tasks, people)} for tasks in setups]
>>> options
[{'Task1': 1, 'Task2': 2, 'Task3': 3}, {'Task1': 1, 'Task2': 2, 'Task4': 3}, {'Task1': 1, 'Task2': 2, 'Task5': 3}, {'Task1': 1, 'Task3':
 2, 'Task4': 3}, {'Task1': 1, 'Task3': 2, 'Task5': 3}, {'Task1': 1, 'Task4': 2, 'Task5': 3}, {'Task2': 1, 'Task3': 2, 'Task4': 3}, {'Tas
k2': 1, 'Task3': 2, 'Task5': 3}, {'Task2': 1, 'Task4': 2, 'Task5': 3}, {'Task3': 1, 'Task4': 2, 'Task5': 3}]

答案 1 :(得分:0)

您可以使用zip()dict()

options = []

for tasks in setup:
    d = dict( zip(tasks,  [Person1, Person2, Person3]) )
    # {'Task1' : Person1, 'Task2' : Person2, 'Task3' : Person3}

    options.append(d)

您的代码taskperson是单个元素,而不是列表 - 您无法使用[0][1]等。

但你可以做(​​使用for/break/else构建)

for option in options:
    for task, person in option.items(): # single elements 
        if task not in person.tasks:
            bad_options.append(option)
            break
    else: # for/break/else construction
        print "OK:", option

答案 2 :(得分:0)

您可以使用以下方法:

class Person(object):
    def __init__(self, id):
        self.id = id            # assign a simple ID to each Person

Person1 = Person(1)
Person2 = Person(2)
Person3 = Person(3)

people = [Person1, Person2, Person3]

setups = (
    ('Task1', 'Task2', 'Task3'),
    ('Task1', 'Task2', 'Task4'),
    ('Task1', 'Task2', 'Task5'))

# Create a list of dictionaries combining each setup with people
options = [dict(zip(setup, people)) for setup in setups]

# Display the list

for option in options:
    for key, person in option.items():
        print key, person.id
    print

这会给你以下输出:

Task1 1
Task2 2
Task3 3

Task1 1
Task2 2
Task4 3

Task1 1
Task2 2
Task5 3
相关问题