关于python:如何展开列表一步

 2019-05-06 

How flatten a list of lists one step

我有一个元组列表

1
A= [ [(1,2,3),(4,5,6)], [(7,8,9),(8,7,6),(5,4,3)],[(2,1,0),(1,3,5)] ]

外部列表可以有任意数量的内部列表,内部列表可以有任意数量的元组,一个元组总是有3个整数。

我要生成所有元组组合,每个列表中一个:

1
2
3
4
5
[(1,2,3),(7,8,9),(2,1,0)]
[(1,2,3),(7,8,9),(1,3,5)]
[(1,2,3),(8,7,6),(2,1,0)]
...
[(4,5,6),(5,4,3),(1,3,5)]

一个简单的方法是使用类似于itertools.poduct()的函数但必须这样叫

1
itertools.product([(1,2,3),(4,5,6)], [(7,8,9),(8,7,6),(5,4,3)],[(2,1,0),(1,3,5)])

即删除外部列表。我不知道该怎么做。有没有更好的方法来生成元组的所有组合?


1
itertools.product(*A)

有关更多详细信息,请查看python教程


派对迟到了,但是…

我对python不熟悉,来自Lisp背景。这就是我想到的(查看lulz的var名称):

1
2
3
4
5
6
7
8
def flatten(lst):
    if lst:
        car,*cdr=lst
        if isinstance(car,(list)):
            if cdr: return flatten(car) + flatten(cdr)
            return flatten(car)
        if cdr: return [car] + flatten(cdr)
        return [car]

似乎起作用了。测试:

1
2
3
A = [ [(1,2,3),(4,5,6)], [(7,8,9),(8,7,6),(5,4,3)],[(2,1,0),(1,3,5)] ]

flatten(A)

结果:

1
[(1, 2, 3), (4, 5, 6), (7, 8, 9), (8, 7, 6), (5, 4, 3), (2, 1, 0), (1, 3, 5)]

注意:行car,*cdr=lst只在python 3.0中工作


您可以这样称呼itertools.product:

1
itertools.product(*A) # where A is your list of lists of tuples

通过这种方式,它将列表的元素扩展为所调用函数的参数。


如果只有一级嵌套列表(没有列表列表列表),则此方法适用于您的示例:

1
itertools.product(*A)

1
2
3
4
5
6
7
8
def flatten(A)
    answer = []
    for i in A:
        if type(i) == list:
            ans.extend(i)
        else:
            ans.append(i)
    return ans


这不是一个简单的步骤,但如果出于某种原因,您不想使用ITertools解决方案,则可以执行以下操作:

1
2
3
4
5
6
7
8
9
10
11
12
def crossprod(listoflists):
    if len(listoflists) == 1:
        return listoflists
    else:
        result = []
        remaining_product = prod(listoflists[1:])
        for outertupe in listoflists[0]:
            for innercombo in remaining_product[0]:
                newcombo = [outertupe]
                newcombo.append(innercombo)
                result.append(newcombo)
        return result


这也可以通过列表理解来实现。

1
2
3
4
5
6
In [62]: A = [ [(1,2,3),(4,5,6)], [(7,8,9),(8,7,6),(5,4,3)],[(2,1,0),(1,3,5)] ]

In [63]: improved_list = [num for elem in A for num in elem]

In [64]: improved_list
Out[64]: [(1, 2, 3), (4, 5, 6), (7, 8, 9), (8, 7, 6), (5, 4, 3), (2, 1, 0), (1, 3, 5)]