我有一个像这样的元组列表:[(1, 2, 3), (2, 4)]
(列表的长度,元组的长度可能会有所不同),我希望得到包含至少一个元素的所有组合列表中的每个元组,以及包含更多元素的那些组合。
所以结果应该在这个例子中:
[[1, 2, 3, 2, 4], [1, 2, 2, 4], [2, 3, 2, 4], [1, 2, 4], [2, 2, 4], [3, 2, 4], [1, 2, 3, 2], [1, 2, 3, 4], [1, 2, 2], [1, 2, 4], [2, 3, 2], [2, 3, 4], [1, 2], [1, 4], [2, 2], [2, 4], [3, 2], [3, 4]]
最小的结果应包含等于原始列表中元组数的元素数,最大的元素应包含元组中存在的所有元素。
元素的顺序无关紧要,应该最终消除重复(所以[1, 2, 3, 2, 4] = [1, 2, 3, 4]
并且应该只在结果中一次,类似[3, 2] = [2, 3]
等),但我想到了排序和/或者在创建整个列表后删除重复项。
最好的方法是什么?坦率地说,我甚至不知道如何正确地开始......
答案 0 :(得分:4)
你想要L中物品的笛卡尔积 - 除非它们中的任何一个是空的。一种方法是在构建powerset时将空元素留下来。
from itertools import product, combinations, chain
L = [(1, 2, 3), (2, 4)]
def powerset(iterable):
"powerset minus the empty element"
s = list(iterable)
return chain.from_iterable(combinations(s, r) for r in range(1, len(s)+1))
print [list(chain.from_iterable(c)) for c in product(*(powerset(x) for x in L))]
打印
[[1, 2], [1, 4], [1, 2, 4], [2, 2], [2, 4], [2, 2, 4], [3, 2], [3, 4], [3, 2, 4], [1, 2, 2], [1, 2, 4], [1, 2, 2, 4], [1, 3, 2], [1, 3, 4], [1, 3, 2, 4], [2, 3, 2], [2, 3, 4], [2, 3, 2, 4], [1, 2, 3, 2], [1, 2, 3, 4], [1, 2, 3, 2, 4]]
答案 1 :(得分:1)
我们将这两个列表用X
和Y
表示,其长度用|X|
和|Y|
表示。
powerset(X)的长度为2^|X|
,而powerset(Y)的长度为2^|Y|
。
因此两个powersets的产品长度为2^(|X|+|Y|)
。
对于本产品中的每个项目,我们需要组合这些部分,取出集合(从部件中删除重复部分)以形成新的集合。然后我们需要使用此集合的集合来删除集合中的重复项。必须采用完整集合的集合可能是内存密集型的,因为它需要立即将完整集合保存在内存中。
但是,我认为有更快的方法来达到理想的最终结果。如果您将X
和Y
合并到一个集XY
中,那么XY
的powerset的长度为2^(|XY|)
。如果2^(|X|+|Y|)
和X
共享任何共同项,则此长度小于Y
。因此,您可以为每个项目共同保存2倍。
对于这个powerset中的每个项目,我们只需要检查X中的元素和Y中的元素。收集所有这些项目,我们就完成了。这样做的工作少得多,并且内存密集程度较低,因为结果可以由迭代器生成。
import itertools as IT
def powerset(iterable, reverse=False, rvals=None):
"""powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"""
s = list(iterable)
N = len(s)
if rvals is None:
rvals = range(N, -1, -1) if reverse else range(N + 1)
return IT.chain.from_iterable(
IT.combinations(s, r) for r in rvals)
def powerreps(X, Y):
"""
Return powerset with at least one representative from X and Y
"""
XY = set(X).union(Y)
for rep in powerset(XY, rvals=range(2, len(XY))):
if any(x in rep for x in X) and any(y in rep for y in Y):
yield rep
X, Y = (1, 2, 3), (2, 4)
print(list(powerreps(X, Y)))
产量
[(1, 2), (1, 4), (2, 3), (2, 4), (3, 4), (1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4), (1, 2, 3, 4)]