Restructure a sequence
Source: Python Morsels
Description
Given an iterable nums
and a “window” of width
, return an
iterator of tuples of the specified width.
1
2
3
>>> numbers = [1, 2, 3, 4, 5, 6]
>>> list(window(numbers, 2))
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
Notes
None.
My solution
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
def window(nums, width):
'''Reformat the iterable `nums` as tuples of `width` each.
Given an iterable `nums` and a "window" of `width`, return an
iterator of tuples of the specified width.
>>> numbers = [1, 2, 3, 4, 5, 6]
>>> list(window(numbers, 2))
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
'''
nums = list(nums)
nlen = len(nums)
for idx in range(nlen):
try:
if idx < nlen - (width - 1):
yield tuple(nums[idx:idx + width])
except IndexError:
pass
# Tests
def test_window_len_even():
numbers = [1, 2, 3, 4, 5, 6]
result = [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
assert list(window(numbers, 2)) == result
def test_iterable_input():
numbers = [1, 2, 3, 4, 5, 6]
squares = (n ** 2 for n in numbers)
result = [(1, 4, 9), (4, 9, 16), (9, 16, 25), (16, 25, 36)]
assert list(window(squares, 3)) == result
# Interaction
if __name__ == '__main__':
print('My tests:')
import doctest, pytest
doctest.testmod()
pytest.main([__file__])
print('Provided tests:')
from os import system
system('python test_window.py')
Provided solution
Uses a deque, which is interesting but seems unnecessary for this particular problem.
1
2
3
4
5
6
7
8
9
10
from collections import deque
from itertools import islice
def window(iterable, n):
iterator = iter(iterable)
current = deque(islice(iterator, n), maxlen=n)
yield tuple(current)
for item in iterator:
current.append(item)
yield tuple(current)