Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions toolz/curried/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
keymap = toolz.curry(toolz.keymap)
map = toolz.curry(toolz.map)
mapcat = toolz.curry(toolz.mapcat)
nonunique = toolz.curry(toolz.nonunique)
nth = toolz.curry(toolz.nth)
partial = toolz.curry(toolz.partial)
partition = toolz.curry(toolz.partition)
Expand Down
44 changes: 33 additions & 11 deletions toolz/itertoolz.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@


__all__ = ('remove', 'accumulate', 'groupby', 'merge_sorted', 'interleave',
'unique', 'isiterable', 'isdistinct', 'take', 'drop', 'take_nth',
'first', 'second', 'nth', 'last', 'get', 'concat', 'concatv',
'mapcat', 'cons', 'interpose', 'frequencies', 'reduceby', 'iterate',
'sliding_window', 'partition', 'partition_all', 'count', 'pluck',
'join', 'tail', 'diff', 'topk', 'peek', 'peekn', 'random_sample')
'unique', 'nonunique', 'isiterable', 'isdistinct', 'take', 'drop',
'take_nth', 'first', 'second', 'nth', 'last', 'get', 'concat',
'concatv', 'mapcat', 'cons', 'interpose', 'frequencies', 'reduceby',
'iterate', 'sliding_window', 'partition', 'partition_all', 'count',
'pluck', 'join', 'tail', 'diff', 'topk', 'peek', 'peekn',
'random_sample')


def remove(predicate, seq):
Expand Down Expand Up @@ -274,6 +275,31 @@ def unique(seq, key=None):
yield item


def nonunique(seq, key=None):
"""Return only nonunique elements of a sequence.

>>> tuple(nonunique((1, 2, 3, 1)))
(1,)
>>> tuple(nonunique((1, 2, 3)))
()
"""
seen = set()
seen_add = seen.add
if key is None:
for item in seq:
if item in seen:
yield item
else:
seen_add(item)
else:
for item in seq:
val = key(item)
if val in seen:
yield item
else:
seen_add(val)


def isiterable(x):
""" Is x iterable?

Expand Down Expand Up @@ -305,12 +331,8 @@ def isdistinct(seq):
True
"""
if iter(seq) is seq:
seen = set()
seen_add = seen.add
for item in seq:
if item in seen:
return False
seen_add(item)
for item in nonunique(seq):
return False
return True
else:
return len(seq) == len(set(seq))
Expand Down
8 changes: 7 additions & 1 deletion toolz/tests/test_itertoolz.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from functools import partial
from random import Random
from pickle import dumps, loads
from toolz.itertoolz import (remove, groupby, merge_sorted,
from toolz.itertoolz import (nonunique, remove, groupby, merge_sorted,
concat, concatv, interleave, unique,
isiterable, getter,
mapcat, isdistinct, first, second,
Expand Down Expand Up @@ -105,6 +105,12 @@ def test_unique():
assert tuple(unique((1, 2, 3), key=iseven)) == (1, 2)


def test_nonunique():
assert tuple(nonunique((1, 2, 3))) == ()
assert tuple(nonunique((1, 2, 1, 3, 1))) == (1, 1)
assert tuple(nonunique((1, 2, 3, 4), key=iseven)) == (3, 4)


def test_isiterable():
assert isiterable([1, 2, 3]) is True
assert isiterable('abc') is True
Expand Down