如何获取Python中二维列表的所有可能组合?

6 投票
3 回答
2406 浏览
提问于 2025-04-17 06:57

我在标题中没找到更好的说法。如果你能的话,请编辑一下。

我有一个这样的列表,里面包含了多个子列表:

a = [['a','b'],[1,2]]

现在,我想要一个函数,能够输出所有可能的组合,像这样:

[['a',1],['a',2],['b',1],['b',2]]

这里面没有提前知道列表的数量,也不知道每个子列表的长度,但所有生成的组合都应该包含每个子列表中的一个项目。

3 个回答

0

这里有一个使用递归的方法,combs_r 函数会把 accumhead(下一个要处理的列表)结合起来,生成一个更大的 accum0,然后再用这个更大的 accum0tail(剩下的列表)再次调用自己,这就是“递归”。

这个方法可能会比较占用内存,因为每次调用 combs_r 都会创建一个新的命名空间,直到最后所有的调用都结束,才会释放这些内存。对Python内部工作原理更了解的人可能会对此有更多评论。

我认为学习Prolog是有好处的。

def combs(ll):
    if len(ll) == 0:
        return []
    if len(ll) == 1:
         return [[item] for item in ll[0]]
    elif len(ll) == 2:
        return lmul(ll[0], [[item] for item in ll[1]])
    else:
        return combs_r(ll[1:], ll[0])

def combs_r(ll, accum):
    head = ll[0]
    tail = ll[1:]
    accum0 = []
    accum0 = lmul(head, accum)
    if len(tail) == 0:
        return accum0
    else:
        return combs_r(tail, accum0)

def lmul(head, accum):
    accum0 = []
    for ah in head:
        for cc in accum:
            #cc will be reused for each ah, so make a clone to mutate
            cc0 = [x for x in cc]
            cc0.append(ah)
            accum0.append(cc0)
    return accum0

sampleip = [['a','b','c'],[1,2], ['A', 'B']]
sampleip2 = [['a','b','c'],[1,2]]
sampleip1 = [['a','b','c']]
sampleip0 = []
print combs(sampleip0)
print combs(sampleip1)
print combs(sampleip2)
print combs(sampleip)
0

这可能就是 itertools.product()(Sven提到的那个)所做的事情:

def combs(list1, list2):
    results = []
    for x in list1:
        for y in list2:
            l.append([x,y])
    return results
14

你需要用到 itertools.product() 这个工具:

>>> list(itertools.product(*a))
[('a', 1), ('a', 2), ('b', 1), ('b', 2)]

撰写回答