如何在python中线性组合列表列表,而不是每个项目都是列表?

问题描述:

我有一个字符串和列表组成的列表:如何在python中线性组合列表列表,而不是每个项目都是列表?

a = ['a', 'b', 'c', 'd', 'e', ['fgh', 'rst'], 'i',['quv','wxy']] 

如何加入每一个元素在此列表中,这样所有的字符串元素包含每个内部列表元素之一,同时保持其原来的位置清单?例如:

targets = ['abcdefghiquv', 
      'abcdefghiwxy', 
      'abcderstiquv', 
      'abcderstiwxy', 
      ] 

我在下面的方式尝试过,但是,如果最后一个元素是一个列表

combinations = [] 
combinations2 = [] 
for s in a: 
    if isinstance(s, basestring): 
     combinations.append(s) 
    else: 
     seqint = ''.join(combinations) 
     combinations2.append([seqint]) 
     combinations2.append(s) 
     combinations[:]=[] 
for comb in list(itertools.product(*combinations2)): 
    print ''.join(comb) 
+1

你尝试过什么已经试图解决这个问题?你能展示你的代码并解释你面临的困难吗? – idjaw

使用itertools.product肯定是要走的路这仅适用。我会做这种方式(可能不完全正确的,因为我从来没有使用传统的Python多):

# helper function 
def strtolist(o): 
    '''Takes an object and puts it in a list if it's a string''' 
    if isinstance(o, str): 
     return [o] 
    return o 

a = ['a', 'b', 'c', 'd', 'e', ['fgh', 'rst'], 'i',['quv','wxy']] 
newa = [strtolist(item) for item in a] 

这最后一步被称为列表理解。它们非常有用,因此它可以很好地利用时间去阅读它们(还有字典理解和生成器理解)。

现在我们有一个新的列表,看起来像这样:

newa = [['a'], ['b'], ['c'], ['d'], ['e'], ['fgh', 'rst'], ['i'],['quv','wxy']] 

然后完成了同之前一样:

from itertools import product 

for comb in list(product(*newa)): 
    print ''.join(comb) 

编辑:如果你真的想要得到粗糙,你可以在一个陈述中完成所有这些。但我不建议这样做(不是很可读):

>>> result = [''.join(combo) for combo in product(*[([item] if isinstance(item, basestr) else item) for item in a])] 
>>> assert result == targets 
# no error: success 

好像你是在学习,所以我会做一个附加注释的过程:除非你有一个很好的理由使用传统学习Python(2),我建议切换到现代Python(当前版本3.6)。这是目前所有的方向(尽管传统的Python在很多情况下可能还会存在很长一段时间)。

通过获取列表索引和使用itertools.product

a = ['a', 'b', 'c', 'd', 'e', ['fgh', 'rst'], 'i',['quv','wxy'] ] 
idx = [] 
lst = [] 
for i in a: 
    if isinstance(i, list): 
     idx.append(a.index(i)) 
     lst.append(i) 

from itertools import product 

for j in [ dict(zip(idx,i)) for i in product(*lst) ] : 
    for k,v in j.items(): 
     a[k] = v 
    print (''.join(a)) 

作为一个实用的风格,你可以reduce列表中的另一种方法:

list(reduce(lambda x, y: (x1 + "".join(y1) for x1 in x for y1 in y), a)) 
['abcdefghiquv', 'abcdefghiwxy', 'abcderstiquv', 'abcderstiwxy']