Skip to content

Commit b2c7fe1

Browse files
Improve grouper() recipe to demonstrate all forms of zip() (GH-30837) (GH-30840)
1 parent e3ade66 commit b2c7fe1

File tree

2 files changed

+41
-9
lines changed

2 files changed

+41
-9
lines changed

Doc/library/itertools.rst

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -813,11 +813,20 @@ which incur interpreter overhead.
813813
return starmap(func, repeat(args))
814814
return starmap(func, repeat(args, times))
815815

816-
def grouper(iterable, n, fillvalue=None):
816+
def grouper(iterable, n, *, incomplete='fill', fillvalue=None):
817817
"Collect data into non-overlapping fixed-length chunks or blocks"
818-
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
818+
# grouper('ABCDEFG', 3, fillvalue='x') --> ABC DEF Gxx
819+
# grouper('ABCDEFG', 3, incomplete='strict') --> ABC DEF ValueError
820+
# grouper('ABCDEFG', 3, incomplete='ignore') --> ABC DEF
819821
args = [iter(iterable)] * n
820-
return zip_longest(*args, fillvalue=fillvalue)
822+
if incomplete == 'fill':
823+
return zip_longest(*args, fillvalue=fillvalue)
824+
if incomplete == 'strict':
825+
return zip(*args, strict=True)
826+
if incomplete == 'ignore':
827+
return zip(*args)
828+
else:
829+
raise ValueError('Expected fill, strict, or ignore')
821830
822831
def triplewise(iterable):
823832
"Return overlapping triplets from an iterable"

Lib/test/test_itertools.py

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2394,6 +2394,21 @@ def test_permutations_sizeof(self):
23942394
... else:
23952395
... return starmap(func, repeat(args, times))
23962396
2397+
>>> def grouper(iterable, n, *, incomplete='fill', fillvalue=None):
2398+
... "Collect data into non-overlapping fixed-length chunks or blocks"
2399+
... # grouper('ABCDEFG', 3, fillvalue='x') --> ABC DEF Gxx
2400+
... # grouper('ABCDEFG', 3, incomplete='strict') --> ABC DEF ValueError
2401+
... # grouper('ABCDEFG', 3, incomplete='ignore') --> ABC DEF
2402+
... args = [iter(iterable)] * n
2403+
... if incomplete == 'fill':
2404+
... return zip_longest(*args, fillvalue=fillvalue)
2405+
... if incomplete == 'strict':
2406+
... return zip(*args, strict=True)
2407+
... if incomplete == 'ignore':
2408+
... return zip(*args)
2409+
... else:
2410+
... raise ValueError('Expected fill, strict, or ignore')
2411+
23972412
>>> def triplewise(iterable):
23982413
... "Return overlapping triplets from an iterable"
23992414
... # pairwise('ABCDEFG') -> ABC BCD CDE DEF EFG
@@ -2411,11 +2426,6 @@ def test_permutations_sizeof(self):
24112426
... window.append(x)
24122427
... yield tuple(window)
24132428
2414-
>>> def grouper(n, iterable, fillvalue=None):
2415-
... "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
2416-
... args = [iter(iterable)] * n
2417-
... return zip_longest(*args, fillvalue=fillvalue)
2418-
24192429
>>> def roundrobin(*iterables):
24202430
... "roundrobin('ABC', 'D', 'EF') --> A D E B F C"
24212431
... # Recipe credited to George Sakkis
@@ -2584,9 +2594,22 @@ def test_permutations_sizeof(self):
25842594
>>> dotproduct([1,2,3], [4,5,6])
25852595
32
25862596
2587-
>>> list(grouper(3, 'abcdefg', 'x'))
2597+
>>> list(grouper('abcdefg', 3, fillvalue='x'))
25882598
[('a', 'b', 'c'), ('d', 'e', 'f'), ('g', 'x', 'x')]
25892599
2600+
>>> it = grouper('abcdefg', 3, incomplete='strict')
2601+
>>> next(it)
2602+
('a', 'b', 'c')
2603+
>>> next(it)
2604+
('d', 'e', 'f')
2605+
>>> next(it)
2606+
Traceback (most recent call last):
2607+
...
2608+
ValueError: zip() argument 2 is shorter than argument 1
2609+
2610+
>>> list(grouper('abcdefg', n=3, incomplete='ignore'))
2611+
[('a', 'b', 'c'), ('d', 'e', 'f')]
2612+
25902613
>>> list(triplewise('ABCDEFG'))
25912614
[('A', 'B', 'C'), ('B', 'C', 'D'), ('C', 'D', 'E'), ('D', 'E', 'F'), ('E', 'F', 'G')]
25922615

0 commit comments

Comments
 (0)