2010-11-20 47 views
10

tôi có một danh sách như thế này:hoán vị của một danh sách liệt kê

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

Tôi muốn chọn một phần tử từ mỗi danh sách và kết hợp chúng trở thành một chuỗi.

Ví dụ: 'AAG', 'aah', 'aar', 'aaw', 'ABG', 'ABH' ....

Tuy nhiên, độ dài của danh sách l và độ dài của mỗi danh sách bên trong đều chưa được biết trước khi chương trình đang chạy. Vì vậy, làm thế nào tôi có thể làm muốn tôi muốn?

+2

Bạn có muốn tất cả các kết hợp hoặc ngẫu nhiên không? – Thomas

+0

Tất cả các kết hợp – wong2

Trả lời

10

Hãy chọn previous solution và sử dụng itertools.product(*l) để thay thế.

+4

Để đánh vần nó: '['' .join (s) cho s trong itertools.product (* l)]' –

+0

@ wong2 bạn có nghĩa là tuyệt vời tôi hy vọng? Fantasy khá khác một chút :) – extraneon

+0

bạn có thể giải thích toán tử * không? tôi cảm thấy như tôi không bao giờ 100% đã nhận nó –

0

Khá dễ dàng với 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')] 
5

Nếu ai hứng thú với các thuật toán, đây là một cách rất đơn giản để sử dụng đệ quy để tìm ra combo:

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) 
0

Ở đây bạn đi

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

Nếu bạn muốn sử dụng lại/tái tạo:

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 
1

sử dụng đệ quy

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) 
1

Piggy-sao tắt của JasonWoof's answer. Sau đây sẽ tạo danh sách thay vì in. Hãy lưu ý rằng điều này có thể rất chậm vì nó đòi hỏi nhiều bộ nhớ để lưu trữ các giá trị.

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

quả

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

Dưới đây là một thay thế tương đương cho itertools.product(*iterables[, repeat]):

Chức năng này tương đương với đoạn mã sau, ngoại trừ việc thực hiện thực tế không xây dựng kết quả trung gian về bộ nhớ:

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) 
Các vấn đề liên quan