islice来自右手边

时间:2017-08-07 12:30:23

标签: python slice itertools deque

对于列表,可以使用切片my_list[-10:]来获取最后一个(最多)10个元素

我想对itertools.islice做同样的事情。在这种情况下,我有一个collections.deque

有没有比以下更有效的方法呢?

from collections import deque
import itertools
my_deque = deque()
my_list = list()
for i in range(100):
    my_deque.append(i)
    my_list.append(i)

然后我们进行切片:

start = max(0, len(my_deque) - 10)
for i in list(itertools.islice(my_deque, start, None)):
    pass

我的时间:

deque: 1000000次循环,每次循环3: 962 ns最佳

列表切片: 10000000次循环,每次循环3: 95.9 ns最佳

1 个答案:

答案 0 :(得分:1)

正如您发现的那样,无法对collections.deque进行切片。但它支持rotation,可以在这种情况下使用:

last_n = 10
my_deque.rotate(last_n)
for i in itertools.islice(my_deque, last_n):
    pass

在这种情况下itertools.islice的问题是它需要迭代所有元素,直到它到达stop。这是因为它通常不仅需要与listdeque等随机访问容器一起使用迭代器。因此,在您的情况下,islice实际上必须遍历deque中的所有元素。使用rotate然后islice,它只需迭代10个元素。

至于时间,很难知道你比较了什么,但使用这个设置:

from collections import deque
import itertools
my_deque = deque(range(10000))
my_list = list(range(10000))

我得到以下时间:

%%timeit

my_deque.rotate(10)
for i in itertools.islice(my_deque, 10):
    pass
my_deque.rotate(-10)  # so the next timing operates on the orginal deque again
  

每回路2.76μs±41.6 ns(平均值±标准偏差,7次运行,每次100000次循环)

%%timeit

start = max(0, len(my_deque) - 10)
for i in itertools.islice(my_deque, start, None):
    pass
  

每循环136μs±8.08μs(平均值±标准差,7次运行,每次10000次循环)

%%timeit

start = max(0, len(my_list) - 10)
for i in itertools.islice(my_list, start, None):
    pass
  

每循环119μs±1.64μs(平均值±标准偏差,7次运行,每次10000次循环)

%timeit my_list[-10:]
  

每回路434 ns±12.5 ns(平均值±标准偏差,7次运行,每次1000000次循环)

所以它不能击败列表切片(仍然慢〜5倍),但它肯定比使用islice方法快得多(~50倍)。