嵌套列表的组合

时间:2016-12-29 21:00:25

标签: python list nested combinations

我有三个由其他功能生成的列表。我们暂时假设它们是:

x = ['d', 'e']
g = ['1', '2']
y = ['f', g]

如您所见,gy的一部分。我试图获得三个列表的元素的所有组合。我试过两种方式来解决这个问题:

一种方式:

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例如为空时,当我仍然希望获得剩余两个列表的元素组合时,我根本没有任何组合。

3 个答案:

答案 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。请注意,这需要提供strbasestring作为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安装)。

flattenitertools 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')]