我会使用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 循环需要额外的操作来确定停止条件。问题在于,对于任意深度的规范灵活性,速度优化是否值得你去做。
至于为什么要使用 reduce 而不是 for,JavaScript 社区一直存在关于是否应该在数组上使用 reduce、map、filter 函数或者使用 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
ranges
给出的数字(n
)(因此是indices
的长度)。列表的深度是“未知”的,但至少有n+1
个子结构。我会更新问题。 - MSeifert