列表列表的所有组合

Lin*_*Lin 210 python combinations

我基本上正在寻找一个python版本的组合List<List<int>>

给定一个列表列表,我需要一个新列表,它列出了列表之间所有可能的项目组合.

[[1,2,3],[4,5,6],[7,8,9,10]] -> [[1,4,7],[1,4,8],...,[3,6,10]]
Run Code Online (Sandbox Code Playgroud)

列表的数量是未知的,所以我需要一些适用于所有情况的东西.优点加分!

Sil*_*ost 376

你需要itertools.product:

>>> import itertools
>>> a = [[1,2,3],[4,5,6],[7,8,9,10]]
>>> list(itertools.product(*a))
[(1, 4, 7), (1, 4, 8), (1, 4, 9), (1, 4, 10), (1, 5, 7), (1, 5, 8), (1, 5, 9), (1, 5, 10), (1, 6, 7), (1, 6, 8), (1, 6, 9), (1, 6, 10), (2, 4, 7), (2, 4, 8), (2, 4, 9), (2, 4, 10), (2, 5, 7), (2, 5, 8), (2, 5, 9), (2, 5, 10), (2, 6, 7), (2, 6, 8), (2, 6, 9), (2, 6, 10), (3, 4, 7), (3, 4, 8), (3, 4, 9), (3, 4, 10), (3, 5, 7), (3, 5, 8), (3, 5, 9), (3, 5, 10), (3, 6, 7), (3, 6, 8), (3, 6, 9), (3, 6, 10)]
Run Code Online (Sandbox Code Playgroud)

  • `*a`表示这些是传递给函数或方法的参数.`def fn(a,b,c):`将响应`fn(*[1,2,3])`[参考](http://www.saltycrane.com/blog/2008/01/how-使用的-ARGS和 - kwargs合蟒/) (44认同)
  • 有人可以在'*a`中解释星号的含义吗? (16认同)
  • @Reman并不完全清楚你想要得到什么,但如果是,例如,每个元组的相反,你可以使用一个包装函数,它以“a”作为输入,迭代“itertools.product(*a)”和“yield”都是由“itertools”生成的元组和反向版本(例如创建一个列表,“reverse()”它并转换回元组)。最好问一个新问题。 (2认同)

Jar*_*die 23

最优雅的解决方案是在python 2.6中使用itertools.product.

如果您不使用Python 2.6,则itertools.product的文档实际上显示了一个等效的函数来以"手动"的方式执行产品:

def product(*args, **kwds):
    # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
    # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
    pools = map(tuple, args) * kwds.get('repeat', 1)
    result = [[]]
    for pool in pools:
        result = [x+[y] for x in result for y in pool]
    for prod in result:
        yield tuple(prod)
Run Code Online (Sandbox Code Playgroud)


Mat*_*hen 18

listOLists = [[1,2,3],[4,5,6],[7,8,9,10]]
for list in itertools.product(*listOLists):
  print list;
Run Code Online (Sandbox Code Playgroud)

我希望你发现它和我第一次遇到它时一样优雅.

  • 那个分号怎么了?:) (4认同)
  • 习惯的力量.我喜欢Python如何让你放一个分号,只是为了帮助我们的C/Java程序员.但很清楚; 当你做类似print("foo")的事情时,它并不是真正的语句终结符; 这在C或Java中完全合法(尽管毫无意义)但在Python中被禁止. (3认同)

dua*_*nev 12

这个任务的直接递归没有错,如果你需要一个处理字符串的版本,这可能适合你的需要:

combinations = []

def combine(terms, accum):
    last = (len(terms) == 1)
    n = len(terms[0])
    for i in range(n):
        item = accum + terms[0][i]
        if last:
            combinations.append(item)
        else:
            combine(terms[1:], item)


>>> a = [['ab','cd','ef'],['12','34','56']]
>>> combine(a, '')
>>> print(combinations)
['ab12', 'ab34', 'ab56', 'cd12', 'cd34', 'cd56', 'ef12', 'ef34', 'ef56']
Run Code Online (Sandbox Code Playgroud)


Dia*_*vas 6

Numpy 可以做到:

 >>> import numpy
 >>> a = [[1,2,3],[4,5,6],[7,8,9,10]]
 >>> [list(x) for x in numpy.array(numpy.meshgrid(*a)).T.reshape(-1,len(a))]
[[ 1, 4, 7], [1, 5, 7], [1, 6, 7], ....]
Run Code Online (Sandbox Code Playgroud)

  • 有人可以解释一下吗? (2认同)
  • 这感觉就像问“我如何烧水”,而不是说“使用水壶”,而是“降低水周围的气压”。两者都有效! (2认同)

rns*_*nso 5

可以使用基础 python 来实现这一点。该代码需要一个函数来展平列表列表:

def flatten(B):    # function needed for code below;
    A = []
    for i in B:
        if type(i) == list: A.extend(i)
        else: A.append(i)
    return A
Run Code Online (Sandbox Code Playgroud)

然后就可以运行:

L = [[1,2,3],[4,5,6],[7,8,9,10]]

outlist =[]; templist =[[]]
for sublist in L:
    outlist = templist; templist = [[]]
    for sitem in sublist:
        for oitem in outlist:
            newitem = [oitem]
            if newitem == [[]]: newitem = [sitem]
            else: newitem = [newitem[0], sitem]
            templist.append(flatten(newitem))

outlist = list(filter(lambda x: len(x)==len(L), templist))  # remove some partial lists that also creep in;
print(outlist)
Run Code Online (Sandbox Code Playgroud)

输出:

[[1, 4, 7], [2, 4, 7], [3, 4, 7], 
[1, 5, 7], [2, 5, 7], [3, 5, 7], 
[1, 6, 7], [2, 6, 7], [3, 6, 7], 
[1, 4, 8], [2, 4, 8], [3, 4, 8], 
[1, 5, 8], [2, 5, 8], [3, 5, 8], 
[1, 6, 8], [2, 6, 8], [3, 6, 8], 
[1, 4, 9], [2, 4, 9], [3, 4, 9], 
[1, 5, 9], [2, 5, 9], [3, 5, 9], 
[1, 6, 9], [2, 6, 9], [3, 6, 9], 
[1, 4, 10], [2, 4, 10], [3, 4, 10], 
[1, 5, 10], [2, 5, 10], [3, 5, 10], 
[1, 6, 10], [2, 6, 10], [3, 6, 10]]
Run Code Online (Sandbox Code Playgroud)