我有三个由其他功能生成的列表。我们暂时假设它们是:
x = ['d', 'e']
g = ['1', '2']
y = ['f', g]
如您所见,g
是y
的一部分。我试图获得三个列表的元素的所有组合。我试过两种方式来解决这个问题:
一种方式:
l = []
l.append([a]+[b] for a in x for b in y)
使用itertools的另一种方式:
import itertools
l = list(itertools.product([a for a in x], [b for b in y]))
两种方式都产生以下组合:
[('d', 'f'), ('d', ['1', '2']), ('e', 'f'), ('e', ['1', '2'])]
但我想得到的是:
[('d', 'f'), ('d', '1'), ('d','2'), ('e', 'f'), ('e', '1'), ('e','2')]
此外,当x
例如为空时,当我仍然希望获得剩余两个列表的元素组合时,我根本没有任何组合。
答案 0 :(得分:6)
在@BrenBarn发表评论时,您可以使用y
函数展开列表chain
,然后使用product
:
from itertools import product, chain
list(product(x, chain.from_iterable(y)))
# [('d', 'f'), ('d', '1'), ('d', '2'), ('e', 'f'), ('e', '1'), ('e', '2')]
答案 1 :(得分:3)
这是受@Psidoms回答的启发,但只是使用专门定制的flatten
函数来确保只迭代应该展平的项目:
def flatten(x, types=list):
lst = []
for item in x:
if isinstance(item, types):
for subitem in item:
lst.append(subitem)
else:
lst.append(item)
return lst
>>> from itertools import product
>>> list(product(x, flatten(y)))
[('d', 'f'), ('d', '1'), ('d', '2'), ('e', 'f'), ('e', '1'), ('e', '2')]
请注意,标准库中不幸没有这样的flatten
函数,但您也可以使用外部库中的函数,例如iteration_utilities.deepflatten
。请注意,这需要提供str
或basestring
作为ignore
:
>>> from iteration_utilities import deepflatten
>>> list(product(x, deepflatten(y, ignore=str)))
[('d', 'f'), ('d', '1'), ('d', '2'), ('e', 'f'), ('e', '1'), ('e', '2')]
要从产品中排除空的iterables,只需排除空的子数据。例如:
>>> x = []
>>> iterables = [subiterable for subiterable in (x, list(deepflatten(y, ignore=str))) if subiterable]
>>> list(product(*iterables))
[('f',), ('1',), ('2',)]
答案 2 :(得分:1)
我想指出more_itertools
中可用的类似扁平函数的两种实现(通过pip install more_itertools
安装)。
flatten
是itertools
recipe并模仿@ Psidom的提案:
import itertools as it
import more_itertools as mit
list(it.product(x, mit.flatten(y)))
# [('d', 'f'), ('d', '1'), ('d', '2'), ('e', 'f'), ('e', '1'), ('e', '2')]
但是,为了展平更深层次的嵌套iterables,请考虑使用collapse
:
# Example
x = ['d', 'e']
g = [('1'), [[['2']]]]
y = [{'f'}, g]
# Bad
list(it.product(x, mit.flatten(y)))
# [('d', 'f'), ('d', '1'), ('d', [[['2']]]), ('e', 'f'), ('e', '1'), ('e', [[['2']]])]
# Good
list(it.product(x, mit.collapse(y)))
# [('d', 'f'), ('d', '1'), ('d', '2'), ('e', 'f'), ('e', '1'), ('e', '2')]