繁体   English   中英

从某个索引开始迭代列表

[英]Iterate over list starting from a certain index

下面是一个例子:

list_ = [5, 'cat', 0xDEADBEEF, 4.0]

for offset in range(len(list_)):
    result = 0
    for elem in list_[offset:]:
        result = func(result, elem)
    return result

其中func是不可交换的。

在上面的代码中, list_[offset:]将创建一个新列表,但我需要的只是list_的视图。 我怎样才能优化这个?

要复制您的切片,但每次迭代的时间为 O(1),您可以将collections.dequepopleft一起popleft

from collections import deque

dq = deque(list_)

for i in range(len(dq)):
    print(dq)
    dq.popleft()

结果:

deque([5, 'cat', 3735928559, 4.0])
deque(['cat', 3735928559, 4.0])
deque([3735928559, 4.0])
deque([4.0])

这应该比列表切片更有效:参见deque.popleft() 和 list.pop(0)。 有性能差异吗? . 还要注意列表切片在 O( k ) 时间内工作,其中k是切片的长度。

正如@jpp 的回答所建议的那样,使用collections.deque有时会稍微快一些 slice 和deque解决方案的性能相似,并且list_如使用itertools.islice或仅在list_上使用普通索引list_

我试图使版本或多或少总体上相等,并使用了一个计算循环的虚拟func

from __future__ import print_function
from collections import deque
from itertools import islice
from timeit import repeat

import numpy as np


list_ = [5, 'cat', 0xDEADBEEF, 4.0]
list_3k = list_ * 3000


def func(x, y):
    return x + 1


def f1():
    """list slice"""
    result = 0
    for offset in range(len(list_)):
        for elem in list_[offset:]:
            result = func(result, elem)
    return result


def f2():
    """deque"""
    dq = deque(list_)
    result = 0
    for i in range(len(dq)):
        for elem in dq:
            result = func(result, elem)
        dq.popleft()
    return result


def f3():
    """itertools slice"""
    result = 0
    for offset in range(len(list_)):
        for elem in islice(list_, offset, None):
            result = func(result, elem)
    return result


def f4():
    """basics"""
    result = 0
    n = len(list_)
    for offset in range(n):
        j = offset
        while j < n:
            result = func(result, list_[j])
            j += 1
    return result


def timeit(fn, number):
    print("{}: {} loops".format(fn.__name__, fn()))
    times = repeat(fn, repeat=3, number=number)
    print("{:.3f}s ± {:.3f}ms".format(np.mean(times), np.std(times)*1000))


if __name__ == "__main__":
    fs = [f1, f2, f3, f4]

    for f in fs:
        timeit(f, number=1000000)

    list_ = list_3k
    print()

    for f in fs:
        timeit(f, number=3)

结果:

bash-3.2$ python3 foo.py 
f1: 10 loops
2.161s ± 9.333ms
f2: 10 loops
2.134s ± 5.127ms
f3: 10 loops
2.340s ± 11.928ms
f4: 10 loops
2.315s ± 4.615ms

f1: 72006000 loops
23.073s ± 109.857ms
f2: 72006000 loops
23.495s ± 596.822ms
f3: 72006000 loops
24.432s ± 553.167ms
f4: 72006000 loops
40.509s ± 128.367ms

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM