通常循环访问未知数量列表的最佳方法



给定一种支持通过列表迭代的编程语言,即

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,继续你的一天。

最新更新