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

6

我在标题中没有找到更好的表达方式,如果可以,请编辑。

我有一个像这样的列表:

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

现在,我希望有一个函数可以输出所有可能的组合,就像这样:

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

当列表a中的列表数量和每个子列表的长度都不确定,并且所有的组合都应该包含每个子列表中的至少1个元素时。

3个回答

14
你需要使用 itertools.product()函数:
>>> list(itertools.product(*a))
[('a', 1), ('a', 2), ('b', 1), ('b', 2)]

对于任何想知道的人,*在列表前面可以解包列表:https://dev59.com/Q3E85IYBdhLWcg3wJQAa#2921893 - wordsforthewise

0

这可能是Sven提到的itertools.product()函数所做的事情:

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

如果我总是只有两个子列表,就像例子[[1,2],['a','b']]一样,那么你只需要将这两个子列表传递给这个函数,它就可以工作。但是实际情况并非如此,列表也可能是[['a','b','c'],[1,2],[{},[],()]],所以现在我们有了三个子列表,因此我们需要一个函数,可以乘以可变数量的列表。 - bigblind
啊,我从你的例子中假设它总是成对出现的。我没有更好的建议了。 - Anko

0

这里有一个使用递归的解决方案,combs_r 使用 accum 消化 head(下一行中的列表)以产生更丰满的 accum0,然后调用自身(“递归”)与 tail(剩余的列表)和现在更丰满的累加器 accum0

每次调用 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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接