Skip to content

Commit 2bd9139

Browse files
authored
Merge pull request #399 from groutr/fix-partition-all
Avoid using .index() in partition_all
2 parents e052d81 + 86953ab commit 2bd9139

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

toolz/itertoolz.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,23 @@ def partition_all(n, seq):
720720
yield prev
721721
prev = item
722722
if prev[-1] is no_pad:
723-
yield prev[:prev.index(no_pad)]
723+
try:
724+
# If seq defines __len__, then
725+
# we can quickly calculate where no_pad starts
726+
yield prev[:len(seq) % n]
727+
except TypeError:
728+
# Get first index of no_pad without using .index()
729+
# https://github.com/pytoolz/toolz/issues/387
730+
# Binary search from CPython's bisect module,
731+
# modified for identity testing.
732+
lo, hi = 0, n
733+
while lo < hi:
734+
mid = (lo + hi) // 2
735+
if prev[mid] is no_pad:
736+
hi = mid
737+
else:
738+
lo = mid + 1
739+
yield prev[:lo]
724740
else:
725741
yield prev
726742

toolz/tests/test_itertoolz.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,17 @@ def test_partition_all():
318318
assert list(partition_all(3, range(5))) == [(0, 1, 2), (3, 4)]
319319
assert list(partition_all(2, [])) == []
320320

321+
# Regression test: https://github.com/pytoolz/toolz/issues/387
322+
class NoCompare(object):
323+
def __eq__(self, other):
324+
if self.__class__ == other.__class__:
325+
return True
326+
raise ValueError()
327+
obj = NoCompare()
328+
result = [(obj, obj, obj, obj), (obj, obj, obj)]
329+
assert list(partition_all(4, [obj]*7)) == result
330+
assert list(partition_all(4, iter([obj]*7))) == result
331+
321332

322333
def test_count():
323334
assert count((1, 2, 3)) == 3

0 commit comments

Comments
 (0)