从右手边切开
islice from right-hand side
对于列表,可以使用切片 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
我的时间:
双端队列: 1000000 次循环,最好的 3: 962 ns
每个循环
列表切片: 10000000 次循环,每次循环 3: 95.9 ns
中最好的
正如您所发现的,无法对 collections.deque
进行切片。但它支持 rotation
可以在这种情况下使用:
last_n = 10
my_deque.rotate(last_n)
for i in itertools.islice(my_deque, last_n):
pass
在这种情况下,itertools.islice
的问题在于它需要遍历所有元素,直到到达 stop
。这是因为它通常需要与迭代器一起工作,而不仅仅是像 list
s 和 deque
s 这样的随机访问容器。因此,在您的情况下,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 per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%%timeit
start = max(0, len(my_deque) - 10)
for i in itertools.islice(my_deque, start, None):
pass
136 µs ± 8.08 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%%timeit
start = max(0, len(my_list) - 10)
for i in itertools.islice(my_list, start, None):
pass
119 µs ± 1.64 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit my_list[-10:]
434 ns ± 12.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
所以它无法击败列表切片(仍然慢 ~5 倍)但它肯定比使用你的 islice
方法快得多(~50 倍)。
对于列表,可以使用切片 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
我的时间:
双端队列: 1000000 次循环,最好的 3: 962 ns
每个循环
列表切片: 10000000 次循环,每次循环 3: 95.9 ns
中最好的
正如您所发现的,无法对 collections.deque
进行切片。但它支持 rotation
可以在这种情况下使用:
last_n = 10
my_deque.rotate(last_n)
for i in itertools.islice(my_deque, last_n):
pass
在这种情况下,itertools.islice
的问题在于它需要遍历所有元素,直到到达 stop
。这是因为它通常需要与迭代器一起工作,而不仅仅是像 list
s 和 deque
s 这样的随机访问容器。因此,在您的情况下,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 per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%%timeit
start = max(0, len(my_deque) - 10)
for i in itertools.islice(my_deque, start, None):
pass
136 µs ± 8.08 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%%timeit
start = max(0, len(my_list) - 10)
for i in itertools.islice(my_list, start, None):
pass
119 µs ± 1.64 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit my_list[-10:]
434 ns ± 12.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
所以它无法击败列表切片(仍然慢 ~5 倍)但它肯定比使用你的 islice
方法快得多(~50 倍)。