itertools和分区集的选择

时间:2015-10-26 11:20:22

标签: python itertools

我有一个列表列表,我们可以将其视为3个带3个球的骨灰盒。

mylist= [
            ['HIGH_1', 'MED_1', 'LOW_1'],
            ['HIGH_2', 'MED_2', 'LOW_2'],
            ['HIGH_3', 'MED_3', 'LOW_3']
        ]

我只允许从每个瓮中选一个球。 我想获得1球,2球和3球的所有组合。在列表列表中回答。

为了达到这个目的,我在每个 urn 中放置一个假元素(无)

mylist= [
            [None, 'HIGH_1', 'MED_1', 'LOW_1'],
            [None, 'HIGH_2', 'MED_2', 'LOW_2'],
            [None, 'HIGH_3', 'MED_3', 'LOW_3']
           ]

现在,以下使用itertools和filter可以获得所需的解决方案。

combos = []
for l in itertools.product(*mylist):
    combos.append(filter(lambda a: a is not None, l))

combos.remove(())   # remove the empty element
print [list(elem) for elem in combos]


[['HIGH_3'], ['MED_3'], ['LOW_3'], ... , ['MED_2', 'HIGH_3'], ['MED_2', 'MED_3'], ['MED_1', 'HIGH_3'], ..., ['LOW_1', 'LOW_2', 'MED_3'], ['LOW_1', 'LOW_2', 'LOW_3']]

产生63个元素。

9(单个元素)+ 27个(两个元素)+ 27个(三个元素)= 63

添加假的并过滤后感觉不是最好的方法。

有没有办法避免这两个看似多余的步骤?

2 个答案:

答案 0 :(得分:1)

您可以使用以下生成器

执行此操作
def combos(data):
    for i in xrange(1, len(data) + 1):
        for item in itertools.combinations(data, i):
            for j in itertools.product(*item):
                yield j

可能是我能想到的最蟒蛇解决方案。

答案 1 :(得分:0)

当您仅附加非空项目时,您不需要remove()。您还可以通过在过滤后立即将项目转换为列表来跳过上一次列表理解。

import itertools
import pprint

mylist= [
            [None, 'HIGH_1', 'MED_1', 'LOW_1'],
            [None, 'HIGH_2', 'MED_2', 'LOW_2'],
            [None, 'HIGH_3', 'MED_3', 'LOW_3']
           ]
combos = []
for item in itertools.product(*mylist):
    combo = list(filter(lambda a: a is not None, item))
    if combo:
        combos.append(combo)

pprint.pprint(combos)

<强>更新

手动插入None并不好。在列表解析中添加一行来执行此操作:

import itertools
import pprint

mylist= [
            ['HIGH_1', 'MED_1', 'LOW_1'],
            ['HIGH_2', 'MED_2', 'LOW_2'],
            ['HIGH_3', 'MED_3', 'LOW_3']
           ]

mylist_with_nones = [[None] + item for item in mylist]
combos = []
for item in itertools.product(*mylist_with_nones):
    combo = list(filter(lambda a: a is not None, item))
    if combo:
        combos.append(combo)

pprint.pprint(combos)