给定一种支持通过列表迭代的编程语言,即
for element in list do
...
如果我们有一个程序将动态数量的列表作为输入,list[1] ... list[n]
(n
可以接受任何值),那么迭代这些列表中的每个元素组合的最佳方法是什么?
例如 list[1] = [1,2]
,list[2] = [1,3]
然后我们遍历[[1,1], [1,3], [2,1], [2,3]]
。
我认为不是很好的想法:
1)将这些列表的一个大产品创建到list_product
中(例如,在Python中,你可以多次使用itertools.product()
),然后迭代list_product
。问题是这需要我们存储一个(潜在的巨大)可迭代对象。
2)找到所有列表长度的乘积,total_length并使用模块化算术类型的想法,按照以下思路做一些事情。
len_lists = [len(list[i]) for i in [1..n]]
total_length = Product(len_lists)
for i in [1 ... total_length] do
total = i-1
list_index = [1...n]
for j in [n ... 1] do
list_index[j] = IntegerPartOf(total / Product([1:j-1]))
total = RemainderOf(total / Product([1:j-1]))
od
print list_index
od
然后打印所有不同组合的list_index
。
在速度方面有没有更好的方法(不太关心可读性)?
1)将这些列表的一个大产品创建到list_product中(例如,在Python中,你可以多次使用itertools.product(),然后迭代list_product。问题是这需要我们存储一个(潜在的巨大)可迭代对象。
itertools
(以及一般的迭代器)的要点是,它们不会一次构造整个结果,而是一次创建一个结果并从结果中返回项。因此,如果您有一个列表列表ListOfLists
并且您希望所有元组都包含其中每个列表中的一个元素,请使用
for elt in itertools.product(*ListOfLists):
...
请注意,您只需呼叫product
一次。它既简单又高效。
您可以使用itertools.product
而无需具体化列表:
>>> from itertools import product
>>> lol = [[1,2],[1,3]]
>>> product(*lol)
<itertools.product object at 0xaa414b4>
>>> for x in product(*lol):
... print x
...
(1, 1)
(1, 3)
(2, 1)
(2, 3)
至于性能,很容易花更多的时间来思考优化它的方法,而不是您希望从优化中获得的收益。 如果你在循环内做任何事情,那么迭代开销本身很可能可以忽略不计。 (最常见的例外是紧密的数字循环,在这种情况下,您应该尝试以数字方式执行此操作。
我的建议是使用itertools.product
,继续你的一天。