我想对我拥有的一些数据进行分类,为此我想链接 python 列表的索引。简化我有一个嵌套列表:

lst = [[[1], [2]], [[3, 3], [4]], [[5], [6,6,6]]]

我想迭代前两个索引的乘积,但保持第三个相同:
from itertools import product

for index1, index2 in product(range(3), range(2)):
    print(lst[index1][index2][0])

但是,我想让这更通用,而无需事先知道这需要深入多少子结构(我想让 range 的数量传递给 itertools.product 变量)。

我正在努力如何概括 [index1][index2][0] 以接受任意数量的 indices ,我能想到的最好的是 functools.reduce :
from functools import reduce

for indices in product(range(3), range(2)):
    print(reduce(list.__getitem__, indices, lst)[0])

这看起来非常复杂(并且比手动索引慢得多),所以我想知道是否有更好更快的方法来做到这一点。我同时使用 python 2.x 和 3.x 并且外部库绝对没问题(但是它不应该需要 NumPy 或基于 NumPy 的包)。

最佳答案

我会为此使用 python 内置的 reduce ,它看起来并不复杂,在我的测试中也没有那么慢:

from itertools import product

for x in product(range(3), range(2)):
    rg = reduce(lambda result, index: result[index], x, lst)
    value = rg[0]

如果您担心 reduce 的时间损失,您可以只使用 for 循环:
for x in product(range(3), range(2)):
    value = lst
    for index in x:
        value = value[index]
    value = value[0]

在所有情况下,这都比手动索引慢,因为 for 循环需要额外的操作来确定停止条件。与往常一样,问题是速度优化对您来说是否值得,因为任意深度规范的灵活性。

至于为什么要使用 reducefor ,JavaScript 社区内一直在争论是应该在 reduce 上使用 mapfilterArray 函数还是使用 for 循环版本,因为它更快,并且你可能想引用那场辩论来选择你站在哪一边。

使用 for 循环计时:
In [22]: stmt = '''
    ...: from itertools import product
    ...: def go():
    ...:   lst = [[[1], [2]], [[3, 3], [4]], [[5], [6,6,6]]]
    ...:   for x in product(range(3), range(2)):
    ...:     # rg = reduce(lambda result, index: result[index], x, lst)
    ...:     value = lst
    ...:     for index in x:
    ...:         value = value[index]
    ...:     value = value[0]
    ...:     # value = lst[x[0]][x[1]][0]
    ...: '''

In [23]: timeit(setup=stmt, stmt='go()', number=1000000)
Out[23]: 4.003296852111816

使用 reduce 计时:
In [18]: stmt = '''
    ...: from itertools import product
    ...: def go():
    ...:   lst = [[[1], [2]], [[3, 3], [4]], [[5], [6,6,6]]]
    ...:   for x in product(range(3), range(2)):
    ...:     rg = reduce(lambda result, index: result[index], x, lst)
    ...:     value = rg[0]
    ...:     # value = lst[x[0]][x[1]][0]
    ...: '''

In [19]: timeit(setup=stmt, stmt='go()', number=1000000)
Out[19]: 6.164631128311157

手动索引计时:
In [16]: stmt = '''
    ...: from itertools import product
    ...: def go():
    ...:   lst = [[[1], [2]], [[3, 3], [4]], [[5], [6,6,6]]]
    ...:   for x in product(range(3), range(2)):
    ...:     # rg = reduce(lambda result, index: result[index], x, lst)
    ...:     value = lst[x[0]][x[1]][0]
    ...: '''

In [17]: timeit(setup=stmt, stmt='go()', number=1000000)
Out[17]: 3.633723020553589

关于python - 为列表链接多个索引操作的最快方法?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41944836/

10-17 00:06