itertools 和从分区集中选择
itertools and selection from partitioned sets
我有一个列表列表,我们可以把它想象成 3 个骨灰盒和 3 个球。
mylist= [
['HIGH_1', 'MED_1', 'LOW_1'],
['HIGH_2', 'MED_2', 'LOW_2'],
['HIGH_3', 'MED_3', 'LOW_3']
]
我只能 select 从每个骨灰盒中取出一个球。
我想得到 1 个球、2 个球和 3 个球的所有组合。在列表列表中回答。
为了实现这一点,我在每个 urn
中放置了一个假元素 (None)
mylist= [
[None, 'HIGH_1', 'MED_1', 'LOW_1'],
[None, 'HIGH_2', 'MED_2', 'LOW_2'],
[None, 'HIGH_3', 'MED_3', 'LOW_3']
]
现在,itertools 和过滤器的以下使用为我提供了所需的解决方案。
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
添加假的 None 和 post 过滤感觉并不是最好的方法。
有没有办法避免这两个看似多余的步骤?
当您仅附加非空项目时,您不需要 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)
您可以使用以下生成器
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
可能是我能想到的最pythonic的解决方案。
我有一个列表列表,我们可以把它想象成 3 个骨灰盒和 3 个球。
mylist= [
['HIGH_1', 'MED_1', 'LOW_1'],
['HIGH_2', 'MED_2', 'LOW_2'],
['HIGH_3', 'MED_3', 'LOW_3']
]
我只能 select 从每个骨灰盒中取出一个球。 我想得到 1 个球、2 个球和 3 个球的所有组合。在列表列表中回答。
为了实现这一点,我在每个 urn
中放置了一个假元素 (None)mylist= [
[None, 'HIGH_1', 'MED_1', 'LOW_1'],
[None, 'HIGH_2', 'MED_2', 'LOW_2'],
[None, 'HIGH_3', 'MED_3', 'LOW_3']
]
现在,itertools 和过滤器的以下使用为我提供了所需的解决方案。
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
添加假的 None 和 post 过滤感觉并不是最好的方法。
有没有办法避免这两个看似多余的步骤?
当您仅附加非空项目时,您不需要 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)
您可以使用以下生成器
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
可能是我能想到的最pythonic的解决方案。