Repository navigation
Expand file tree
/
Copy pathtakeevery.py
More file actions
148 lines (126 loc) · 3.91 KB
/
Copy pathtakeevery.py
File metadata and controls
148 lines (126 loc) · 3.91 KB
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
"""every(iterable, n) yields lists of size at most n from iterable, until the
iterable is exhausted.
Example: taking every N elements from nothing -- nothing is taken.
>>> import six
>>> for t in every([], 11):
... print(t)
Example: taking every N elements from an unending generator -- can always take
more.
>>> def integers():
... i = 0
... while True:
... yield i
... i += 1
>>> t = every(integers(), 3)
>>> next(t)
[0, 1, 2]
>>> next(t)
[3, 4, 5]
Example: taking nothing from an infinite generator -- nothing is ever taken.
>>> tp = ievery(integers(), 0)
>>> next(tp)
Traceback (most recent call last):
...
StopIteration
>>> next(tp)
Traceback (most recent call last):
...
StopIteration
Example: taking nothing from a finite sequence -- nothing is ever taken.
>>> for item in every([0, 1], 0):
... print(item)
Example: taking more than what is available -- exhausts everything.
>>> for item_iter in ievery([0, 1], 10):
... for item in item_iter:
... six.print_(item, end=" ")
... six.print_()
0 1
Example: taking nothing from nothing -- nothing is taken.
>>> tp = every([], 0)
>>> next(tp)
Traceback (most recent call last):
...
StopIteration
Example: composite taking -- inner generator takes first.
>>> a = sm.range(11)
>>> t = every(every(a, 2), 3)
>>> for item in t:
... print(item)
[[0, 1], [2, 3], [4, 5]]
[[6, 7], [8, 9], [10]]
>>> a = sm.range(7)
>>> t = every(every(a, 3), 2)
>>> for item in t:
... print(item)
[[0, 1, 2], [3, 4, 5]]
[[6]]
Example: taking from heterogeneous sequence -- nothing special.
>>> for item in every((0, 1, [2], [], None, [5, 6], [[[]]], [8]), 3):
... print(item)
[0, 1, [2]]
[[], None, [5, 6]]
[[[[]]], [8]]
"""
from itertools import chain, islice
import six.moves as sm
def ievery(iterable, n):
"""ievery(iterable, n) generates "sub-iterator" objects.
Each generated sub-iterator object can be exhausted by at most n
iterations, and the first sub-iterable yields the first n (or all) elements
from "iterable", and so on.
Notice that apart from a look-ahead of size one to determine whether the
"ievery" generator object should reach the stopped state as early as it
can, this generator does not exhaust the original iterable. The
sub-iterators yielded by "ievery" only define a pattern of iteration to be
applied to the original iterable. The actual consumption of the original
iterable must be done by starting the sub-iterators.
A consequence is that during the consumption of sub-iterators, if the
iteration stops early, without exhausting the current sub-iterator, the
next sub-iterator will resume from the place next to the last stop.
Therefore, it probably doesn't do what you mean to do by creating the next
sub-iterator without starting the current one.
Example: using a series of sub-iterators to take every 3 elements from an
integer sequence.
>>> import six
>>> for subiter in ievery(range(5), 3):
... for item in subiter:
... six.print_(item, end=" ")
... six.print_()
0 1 2
3 4
Example: early break.
>>> for i, b in enumerate(ievery(range(13), 3)):
... for j, t in enumerate(b):
... six.print_(t, end=" ")
... if i == 1 and j == 0:
... break
... six.print_()
0 1 2
3
4 5 6
7 8 9
10 11 12
"""
it = iter(iterable)
while True:
raw_batch = islice(it, n)
try:
head = next(raw_batch)
except StopIteration:
break
yield chain((head,), raw_batch)
def every(iterable, n):
"""every(ABCDEFG, 2) --> [AB] [CD] [EF] [G]
>>> a = range(5)
>>> s = every(a, 2)
>>> for batch in s:
... print(batch)
[0, 1]
[2, 3]
[4]
"""
for batch_iter in ievery(iterable, n):
yield list(batch_iter)
if __name__ == "__main__":
import doctest
doctest.testmod()