Skip to content

Commit 8baf009

Browse files
committed
add allsame: test if all elements of an iterable are the same
Checked using `!=`.
1 parent ef33f16 commit 8baf009

File tree

3 files changed

+32
-2
lines changed

3 files changed

+32
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
- `callsite_filename`: return the filename from which this function is being called. Useful as a building block for debug utilities and similar.
1111
- `equip_with_traceback`: take a manually created exception instance, equip it with a traceback. Requires Python 3.7 or later.
1212
- `subset`: test whether an iterable is a subset of another. Convenience function.
13+
- `allsame`: test whether all elements of an iterable are the same. Sometimes useful in writing testing code.
1314

1415
**Non-breaking changes**:
1516

unpythonic/it.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
"window", "chunked",
2929
"within", "fixpoint",
3030
"interleave",
31-
"subset", "powerset"]
31+
"subset", "powerset",
32+
"allsame"]
3233

3334
from builtins import map as stdlib_map
3435
from operator import itemgetter
@@ -991,3 +992,24 @@ def total_num_items(ld):
991992
bag.append(x)
992993
yield from t
993994
bag.extend(t)
995+
996+
def allsame(iterable):
997+
"""Return whether all elements of an iterable are the same.
998+
999+
The test uses `!=` to compare.
1000+
1001+
If `iterable` is empty, the return value is `True` (like for `all`).
1002+
1003+
If `iterable` has just one element, the return value is `True`.
1004+
1005+
**CAUTION**: Consumes consumable iterables.
1006+
"""
1007+
it = iter(iterable)
1008+
try:
1009+
x0 = next(it)
1010+
except StopIteration:
1011+
return True # like all(()) is True
1012+
for x in it:
1013+
if x != x0:
1014+
return False
1015+
return True

unpythonic/test/test_it.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
window, chunked,
2727
within, fixpoint,
2828
interleave,
29-
subset, powerset)
29+
subset, powerset,
30+
allsame)
3031

3132
from ..fun import composel, identity, curry
3233
from ..gmemo import imemoize, gmemoize
@@ -345,6 +346,12 @@ def sqrt_iter(x): # has an attractive fixed point at sqrt(n)
345346
test[all(sum(terms) == 10 for terms in partition_int(10, lower=3))]
346347
test[all(sum(terms) == 10 for terms in partition_int(10, lower=3, upper=5))]
347348

349+
with testset("allsame"):
350+
test[allsame(())]
351+
test[allsame((1,))]
352+
test[allsame((8, 8, 8, 8, 8))]
353+
test[not allsame((1, 2, 3))]
354+
348355
if __name__ == '__main__': # pragma: no cover
349356
with session(__file__):
350357
runtests()

0 commit comments

Comments
 (0)