3 个列表之间的 Python 组合,一个列表依赖于一个列表

Python combinations between 3 lists with one depending on one list

提问人:CornelioQuinto 提问时间:8/18/2023 更新时间:11/24/2023 访问量:94

问:

我有两个列表和第三个列表,它依赖于第一个列表。

l1 = [1, 2]
l2 = [3, 4]

l3 = [[11, 111], [22, 222]] # the numbers are calculated for each element of l1

我想要的是创建一个组合,从而产生:

[(1,3,11), (1,3,111), (1,4,11), (1,4,111), (2,3,22), (2,3,222), (2,4,22), (2,4,222)]

你有什么建议吗?

列表 元组 组合 python-itertools

评论

2赞 Kelly Bundy 8/18/2023
我们不知道第三个如何取决于第一个,你们不告诉我们。

答:

0赞 C. McCracken 8/18/2023 #1

这个怎么样?

tuples = []
for l1_index, a in enumerate(l1):
    for b in l2:
         for c in l3[l1_index]:
             tuples.append((a,b,c))
print(tuples)

>>> [(1, 3, 11), (1, 3, 111), (1, 4, 11), (1, 4, 111), (2, 3, 22), (2, 3, 222), (2, 4, 22), (2, 4, 222)]

评论

0赞 Kelly Bundy 8/18/2023
尝试for a, cs in zip(l1, l3):
0赞 Alain T. 8/18/2023 #2

l1 和 l3 之间的关系尚不清楚,但假设它只是位置关系,您可以使用带有 zip() 的嵌套推导式来组合 l1 和 l3:

[ (a,b,c) for a,ac in zip(l1,l3) for b in l2 for c in ac  ]

[(1, 3, 11), (1, 3, 111), (1, 4, 11), (1, 4, 111), (2, 3, 22), 
 (2, 3, 222), (2, 4, 22), (2, 4, 222)]
-1赞 Ben A. 8/18/2023 #3

这是我的尝试:

def combine_lists(l1, l2, l3):
    result = []
    for index, i in enumerate(l1):
        for j in l2:
            result.append((i, j, l3[index][0]))
            result.append((i, j, l3[index][1]))
    return result

运行以下命令将生成您描述的结果:

l1 = [1, 2]
l2 = [3, 4]
l3 = [[11, 111], [22, 222]]

combination = combine_lists(l1, l2, l3)
print(combination)
-2赞 CornelioQuinto 8/18/2023 #4

谢谢大家!最后,我得到了这个:

combo = []
for i in range(len(l1)):
    for j in range(len(l2)):
        for k in range(len(l3[i])):
            combo.append((l1[i], l2[j], l3[i][k]))
            
combo
0赞 bfontaine 8/21/2023 #5

这将起作用:

import itertools                                                                     

combo = list(itertools.chain(*[                                                          
    itertools.product([l1[i]], l2, l3[i])                                            
    for i in range(len(l1))                                                          
]))

这循环了 ,对于每个第 th 个元素,它都会生成与该元素的所有组合,后跟 中第 个列表中的任何一个和任何一个。l1il2il3

合并所有组合列表的调用也可以重写为列表推导式:itertools.chain

combo3 = [
    e
    for i in range(len(l1))
    for e in itertools.product([l1[i]], l2, l3[i])
]

包含长度为 100、 和 1000 次迭代(代码)的所有列表的快速基准测试:len(l3[i]) == 5

评论

0赞 Kelly Bundy 8/21/2023
使用 itertools 似乎很奇怪,但避免 zip...
1赞 Kelly Bundy 8/21/2023
还有另一种方法,通过使用 map 摆脱所有 Python 迭代: 。艺术list(itertools.chain(*map( itertools.product, zip(l1), itertools.repeat(l2), l3 )))list(itertools.chain.from_iterable(map( itertools.product, zip(l1), itertools.repeat(l2), l3 )))
0赞 bfontaine 8/21/2023
@KellyBundy是获得产品的强制性要求,但不是。itertoolszip
0赞 Kelly Bundy 8/21/2023
但是,使用繁重的导入工具而不使用较小的内置工具,而是使用非 pythonic 索引循环仍然很奇怪。等等,你认为我后来的替代方式是指拉链吗?我没有。我的意思是 l1 和 l3 的并行迭代,正如我在 C. McCracken 的回答中所建议的那样。
0赞 bfontaine 8/21/2023
@KellyBundy 实际上,我发现 McCracken 的答案没有它比有它更容易阅读,但我想使用正确的命名(而不仅仅是 //)它会是一样的。zipabc