Skip to content

Instantly share code, notes, and snippets.

@mpkocher
Last active December 18, 2019 23:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mpkocher/7beab201b2efad6232f84540864d7dd7 to your computer and use it in GitHub Desktop.
Save mpkocher/7beab201b2efad6232f84540864d7dd7 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
from collections import deque
def to_tail(it, max_items):
"""
https://twitter.com/Wildvasa/status/1207383049387810816
Get the last N elements from an iterable
This modification will avoid reading in the
entire iterable into memory if possible.
"""
# this will sort out the impedance mismatch
ix = iter(it)
dq = deque(maxlen=max_items)
# this needs to be tuned to
# clarify the expected behavior
# when the max_items is longer
# than the iterable and when the
# iterable is empty
for i in range(0, max_items):
try:
item = next(ix)
dq.append(item)
except StopIteration:
pass
for i in ix:
# O(1)
dq.popleft()
dq.append(i)
for x in dq:
yield x
def test_to_tail():
def to_gen(max_items):
for i in range(0, max_items):
yield i * i
def run(it, max_items):
print("running it={} type={} max-items={}".format(it, type(it), max_items))
print(list(to_tail(it, max_items)))
print("")
tests = [
(range(0, 10), 3),
(range(0, 20), 5),
(to_gen(10), 3),
(to_gen(10), 15),
(to_gen(20), 2),
([1, 2, 3], 1),
('abcd', 3)
]
for it, max_items in tests:
run(it, max_items)
if __name__ == '__main__':
test_to_tail()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment