简体   繁体   English

列表列表的排列

[英]Permutations of a list of lists

I have a list like this: 我有一个这样的列表:

l = [['a', 'b', 'c'], ['a', 'b'], ['g', 'h', 'r', 'w']]

I want to pick an element from each list and combine them to be a string. 我想从每个列表中选择一个元素并将它们组合成一个字符串。

For example: 'aag', 'aah', 'aar', 'aaw', 'abg', 'abh' .... 例如:'aag','aah','aar','aaw','abg','abh'....

However, the length of the list l and the length of each inner list are all unknown before the program is running. 但是,在程序运行之前,列表l的长度和每个内部列表的长度都是未知的。 So how can I do want I want? 那我怎么能想要我想要的?

采用以前的解决方案并使用itertools.product(*l)代替。

If anybody's interested in the algorithm, here's a very simple way to use recursion to find the combos: 如果有人对算法感兴趣,这是使用递归来查找组合的一种非常简单的方法:

 l = [['a', 'b', 'c'], ['a', 'b'], ['g', 'h', 'r', 'w']]
 def permu(lists, prefix=''):
      if not lists:
           print prefix
           return
      first = lists[0]
      rest = lists[1:]
      for letter in first:
           permu(rest, prefix + letter)
 permu(l)

Piggy-backing off of JasonWoof's answer . JasonWoof回答的小猪退学 The following will create a list instead of printing. 以下将创建列表而不是打印。 Be mindful that this may be very slow as it requires a lot of memory to store the values. 请注意,这可能会非常慢,因为它需要大量内存来存储值。

from __future__ import print_function
import itertools # Not actually used in the code below

def permu(lists):
    def fn(lists, group=[], result=[]):
        if not lists:
            result.append(group)
            return
        first, rest = lists[0], lists[1:]
        for letter in first:
            fn(rest, group + [letter], result)
    result = []
    fn(lists, result=result)
    return result

if __name__ == '__main__':
    ll = [ [[1, 2, 3], [5, 10], [42]],
           [['a', 'b', 'c'], ['a', 'b'], ['g', 'h', 'r', 'w']] ]
    nth = lambda i: 'Permutation #{0}:\n{1}'.format(i, '-'*16)

    # Note: permu(list) can be replaced with itertools.product(*l)
    [[print(p) for p in [nth(i)]+permu(l)+['\n']] for i,l in enumerate(ll)]

Result 结果

Permutation #0:
----------------
[1, 5, 42]
[1, 10, 42]
[2, 5, 42]
[2, 10, 42]
[3, 5, 42]
[3, 10, 42]


Permutation #1:
----------------
['a', 'a', 'g']
['a', 'a', 'h']
['a', 'a', 'r']
['a', 'a', 'w']
['a', 'b', 'g']
['a', 'b', 'h']
['a', 'b', 'r']
['a', 'b', 'w']
['b', 'a', 'g']
['b', 'a', 'h']
['b', 'a', 'r']
['b', 'a', 'w']
['b', 'b', 'g']
['b', 'b', 'h']
['b', 'b', 'r']
['b', 'b', 'w']
['c', 'a', 'g']
['c', 'a', 'h']
['c', 'a', 'r']
['c', 'a', 'w']
['c', 'b', 'g']
['c', 'b', 'h']
['c', 'b', 'r']
['c', 'b', 'w']

Below is an equivalent substitution for itertools.product(*iterables[, repeat]) : 下面是itertools.product(*iterables[, repeat])的等效替换:

This function is equivalent to the following code, except that the actual implementation does not build up intermediate results in memory: 此函数等效于以下代码,但实际实现不会在内存中构建中间结果:

 def product(*args, **kwds): 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) 

Quite easy with itertools.product : 使用itertools.product非常简单:

>>> import itertools
>>> list(itertools.product("abc", "ab", "ghrw"))
[('a', 'a', 'g'), ('a', 'a', 'h'), ('a', 'a', 'r'), ('a', 'a', 'w'), ('a', 'b', 'g'), ('a', 'b', 'h'), ('a', 'b', 'r'), ('a', 'b', 'w'), ('b', 'a', 'g'), ('b', 'a', 'h'), ('b', 'a', 'r'), ('b', 'a', 'w'), ('b', 'b', 'g'), ('b', 'b', 'h'), ('b', 'b', 'r'), ('b', 'b', 'w'), ('c', 'a', 'g'), ('c', 'a', 'h'), ('c', 'a', 'r'), ('c', 'a', 'w'), ('c', 'b', 'g'), ('c', 'b', 'h'), ('c', 'b', 'r'), ('c', 'b', 'w')]

using recursion 使用递归

def permutenew(l):
if len(l)==1:
    return l[0]
else:   
    lnew=[]
    for a in l[0]:
        for b in permutenew(l[1:]):
            lnew.append(a+b)
    return lnew

l = [['a', 'b', 'c'], ['a', 'b'], ['g', 'h', 'r', 'w']]
print permutenew(l)

Here you go 干得好

reduce(lambda a,b: [i+j for i in a for j in b], l)

OUT: ['aag', 'aah', 'aar', 'aaw', 'abg', 'abh', 'abr', 'abw', 'bag', 'bah', 'bar', 'baw', 'bbg', 'bbh', 'bbr', 'bbw', 'cag', 'cah', 'car', 'caw', 'cbg', 'cbh', 'cbr', 'cbw']

If you'd like to reuse/regeneralize: 如果您想重复使用/重新生成:

def opOnCombos(a,b, op=operator.add):
    return [op(i,j) for i in a for j in b]

def f(x):
    return lambda a,b: opOnCombo(a,b,x)

reduce(opOnCombos, l) //same as before
reduce(f(operator.mul), l))  //multiply combos of several integer list

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM