Python 列表列表的所有组合
Python all combinations of a list of lists
所以我有一个字符串列表列表
[['a','b'],['c','d'],['e','f']]
我想得到所有可能的组合,这样的结果是
[['a','b'],['c','d'],['e','f'],
['a','b','c','d'],['a','b','e','f'],['c','d','e','f'],
['a','b','c','d','e','f']]
到目前为止我已经想出了这个代码片段
input = [['a','b'],['c','d'],['e','f']]
combs = []
for i in xrange(1, len(input)+1):
els = [x for x in itertools.combinations(input, i)]
combs.extend(els)
print combs
主要遵循 this post 中的答案。
但这会导致
[(['a','b'],),(['c','d'],),(['e','f'],),
(['a','b'],['c','d']),(['a','b'],['e','f']),(['c','d'],['e','f']),
(['a','b'],['c', 'd'],['e', 'f'])]
我现在很困惑,试图找到一种优雅的 pythonic 方式来解压这些元组。
您可以使用 itertools.chain.from_iterable
将列表的元组展平为一个列表。例子-
import itertools
input = [['a','b'],['c','d'],['e','f']]
combs = []
for i in xrange(1, len(input)+1):
els = [list(itertools.chain.from_iterable(x)) for x in itertools.combinations(input, i)]
combs.extend(els)
演示 -
>>> import itertools
>>> input = [['a','b'],['c','d'],['e','f']]
>>> combs = []
>>> for i in range(1, len(input)+1):
... els = [list(itertools.chain.from_iterable(x)) for x in itertools.combinations(input, i)]
... combs.extend(els)
...
>>> import pprint
>>> pprint.pprint(combs)
[['a', 'b'],
['c', 'd'],
['e', 'f'],
['a', 'b', 'c', 'd'],
['a', 'b', 'e', 'f'],
['c', 'd', 'e', 'f'],
['a', 'b', 'c', 'd', 'e', 'f']]
这个目标的一个想法是根据一个非常简单的规则将整数从 [0..2**n-1]
映射到所有目标元素,其中 n 是子列表的数量:
取索引 k if (2**k)&i!=0
where i run over [0..2**n-1]
的元素。换句话说,i 必须按位读取,并且对于每个位集,保留 l 中的对应元素。从数学的角度来看,它是实现你想要做的事情的最干净的方法之一,因为它非常严格地遵循集合部分的定义(对于具有 n 个元素的集合,你正好有 2**n
个部分).
没试过,但类似的东西应该有用:
l = [['a','b'],['c','d'],['e','f']]
n = len(l)
output = []
for i in range(2**n):
s = []
for k in range(n):
if (2**k)&i: s = s + l[k]
output.append(s)
如果您不想要空列表,只需将相关行替换为:
for i in range(1,2**n):
如果你想要所有的组合,你可以考虑这个简单的方法:
import itertools
a = [['a','b'],['c','d'],['e','f']]
a = a + [i + j for i in a for j in a if i != j] + [list(itertools.chain.from_iterable(a))]
有理解列表:
combs=[sum(x,[]) for i in range(len(l)) for x in itertools.combinations(l,i+1)]
所以我有一个字符串列表列表
[['a','b'],['c','d'],['e','f']]
我想得到所有可能的组合,这样的结果是
[['a','b'],['c','d'],['e','f'],
['a','b','c','d'],['a','b','e','f'],['c','d','e','f'],
['a','b','c','d','e','f']]
到目前为止我已经想出了这个代码片段
input = [['a','b'],['c','d'],['e','f']]
combs = []
for i in xrange(1, len(input)+1):
els = [x for x in itertools.combinations(input, i)]
combs.extend(els)
print combs
主要遵循 this post 中的答案。
但这会导致
[(['a','b'],),(['c','d'],),(['e','f'],),
(['a','b'],['c','d']),(['a','b'],['e','f']),(['c','d'],['e','f']),
(['a','b'],['c', 'd'],['e', 'f'])]
我现在很困惑,试图找到一种优雅的 pythonic 方式来解压这些元组。
您可以使用 itertools.chain.from_iterable
将列表的元组展平为一个列表。例子-
import itertools
input = [['a','b'],['c','d'],['e','f']]
combs = []
for i in xrange(1, len(input)+1):
els = [list(itertools.chain.from_iterable(x)) for x in itertools.combinations(input, i)]
combs.extend(els)
演示 -
>>> import itertools
>>> input = [['a','b'],['c','d'],['e','f']]
>>> combs = []
>>> for i in range(1, len(input)+1):
... els = [list(itertools.chain.from_iterable(x)) for x in itertools.combinations(input, i)]
... combs.extend(els)
...
>>> import pprint
>>> pprint.pprint(combs)
[['a', 'b'],
['c', 'd'],
['e', 'f'],
['a', 'b', 'c', 'd'],
['a', 'b', 'e', 'f'],
['c', 'd', 'e', 'f'],
['a', 'b', 'c', 'd', 'e', 'f']]
这个目标的一个想法是根据一个非常简单的规则将整数从 [0..2**n-1]
映射到所有目标元素,其中 n 是子列表的数量:
取索引 k if (2**k)&i!=0
where i run over [0..2**n-1]
的元素。换句话说,i 必须按位读取,并且对于每个位集,保留 l 中的对应元素。从数学的角度来看,它是实现你想要做的事情的最干净的方法之一,因为它非常严格地遵循集合部分的定义(对于具有 n 个元素的集合,你正好有 2**n
个部分).
没试过,但类似的东西应该有用:
l = [['a','b'],['c','d'],['e','f']]
n = len(l)
output = []
for i in range(2**n):
s = []
for k in range(n):
if (2**k)&i: s = s + l[k]
output.append(s)
如果您不想要空列表,只需将相关行替换为:
for i in range(1,2**n):
如果你想要所有的组合,你可以考虑这个简单的方法:
import itertools
a = [['a','b'],['c','d'],['e','f']]
a = a + [i + j for i in a for j in a if i != j] + [list(itertools.chain.from_iterable(a))]
有理解列表:
combs=[sum(x,[]) for i in range(len(l)) for x in itertools.combinations(l,i+1)]