多个列表中的元素做组合的逻辑与python实现

引入

本文组合逻辑的讲解,与代码,都是基于python的。

我们在实际编程中,会遇到多个元素做组合的过程,比如,给定如下4个列表

list1 = ['A', 'B']
list2 = ['C', 'D']
list3 = ['E','F','G']
list4 = ['H', 'I']

列表中的元素(A/B/C等),这里用的是string。实际情况中,也可以是int,或其他类型的instance(比如list)。

若要求每个list中的元素,分别于其他list的元素做组合,最终组合结果如下,该怎么求解呢?

[['A', 'C', 'E', 'H'],
 ['A', 'C', 'E', 'I'],
 ['A', 'C', 'F', 'H'],
 ['A', 'C', 'F', 'I'],
 ['A', 'C', 'G', 'H'],
 ['A', 'C', 'G', 'I'],
 ['A', 'D', 'E', 'H'],
 ['A', 'D', 'E', 'I'],
 ['A', 'D', 'F', 'H'],
 ['A', 'D', 'F', 'I'],
 ['A', 'D', 'G', 'H'],
 ['A', 'D', 'G', 'I'],
 ['B', 'C', 'E', 'H'],
 ['B', 'C', 'E', 'I'],
 ['B', 'C', 'F', 'H'],
 ['B', 'C', 'F', 'I'],
 ['B', 'C', 'G', 'H'],
 ['B', 'C', 'G', 'I'],
 ['B', 'D', 'E', 'H'],
 ['B', 'D', 'E', 'I'],
 ['B', 'D', 'F', 'H'],
 ['B', 'D', 'F', 'I'],
 ['B', 'D', 'G', 'H'],
 ['B', 'D', 'G', 'I']]

这里最简单的解法,就是用4个for循环来实现。但实际情况中,list的个数是可变的,那就无法用固定个数的for训练来实现了。

我们下面就讲解这个问题的求解逻辑,与代码实现。

组合的逻辑过程

首先,把所有list都装在一个list中,比如

all_list = [list1, list2, list3, list4]

然后,设置一个空的result的list,用来存储最终结果

result = [[]]

这里是list of list,其中的内层list设置为空list很重要,这保证了下面逻辑的正确进行。

接下来,遍历各个子list的元素,并与result中的元素做组合:

for pool in all_list:
    tmp = []
    for x in result:
        for y in pool:
            tmp.append(x+[y])
    result = tmp   

为了看懂上面代码的组合逻辑过程,我们写一个简化的实例,如下:

all_list = [['A','B'],['C','D','E']]
result = [[]]

for pool in all_list:
    tmp = []
    for x in result:
        for y in pool:
            tmp.append(x+[y])
            print(tmp)
    result = tmp   

跑起来,得到的输出如下

[['A'], ['B']]
[['A', 'C'], ['A', 'D'], ['A', 'E']]
[['A', 'C'], ['A', 'D'], ['A', 'E'], ['B', 'C'], ['B', 'D'], ['B', 'E']]

通过输出,可以看到,组合的过程,就是

  1. 先把list1的元素(['A','B']),append到result中
result = [['A'], ['B']]
  1. 把上面的result与list2中每个元素(['C','D','E'])做组合,再更新result
result = [['A', 'C'], ['A', 'D'], ['A', 'E'], ['B', 'C'], ['B', 'D'], ['B', 'E']]
  1. 如果还有list3,再进行2的过程

这里有个小经验,就是将多个list放入一个list中,就避免了for的个数不确定的问题。

最终,使用这段代码,就解决了本文开头提出的问题:

all_list = [['A', 'B'], ['C', 'D'], ['E','F','G'], ['H', 'I']]
result = [[]]

for pool in all_list:
    tmp = []
    for x in result:
        for y in pool:
            tmp.append(x+[y])
    result = tmp   

print(result)

使用itertools

上面的逻辑过程,已经被itertools做了更强大的实现,可以用更简洁的代码来解决问题:

import itertools
all_list = [['A', 'B'], ['C', 'D'], ['E','F','G'], ['H', 'I']]
list(itertools.product(*all_list))

注意,*all_list的用法,是为函数传入多个参数(不确定参数个数)的语法。

itertools很多源代码都放到文档中了,可以在[1]中查看itertools的很多方法源码。

上面的代码,其实就是itertools中product的部分源码。

参考

  • [1] https://docs.python.org/3/library/itertools.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章