Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reduceby defaults to item in no init case #184

Merged
merged 1 commit into from
Jun 8, 2014
Merged
Show file tree
Hide file tree
Changes from all 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
24 changes: 19 additions & 5 deletions toolz/itertoolz.py
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ def frequencies(seq):
return dict(d)


def reduceby(key, binop, seq, init):
def reduceby(key, binop, seq, init=no_default):
""" Perform a simultaneous groupby and reduction

The computation:
Expand All @@ -468,18 +468,28 @@ def reduceby(key, binop, seq, init):
operate in much less space. This makes it suitable for larger datasets
that do not fit comfortably in memory

Simple Examples
---------------

>>> from operator import add, mul
>>> data = [1, 2, 3, 4, 5]
>>> iseven = lambda x: x % 2 == 0
>>> reduceby(iseven, add, data, 0)

>>> data = [1, 2, 3, 4, 5]

>>> reduceby(iseven, add, data)
{False: 9, True: 6}
>>> reduceby(iseven, mul, data, 1)

>>> reduceby(iseven, mul, data)
{False: 15, True: 8}

Complex Example
---------------

>>> projects = [{'name': 'build roads', 'state': 'CA', 'cost': 1000000},
... {'name': 'fight crime', 'state': 'IL', 'cost': 100000},
... {'name': 'help farmers', 'state': 'IL', 'cost': 2000000},
... {'name': 'help farmers', 'state': 'CA', 'cost': 200000}]

>>> reduceby(lambda x: x['state'], # doctest: +SKIP
... lambda acc, x: acc + x['cost'],
... projects, 0)
Expand All @@ -489,7 +499,11 @@ def reduceby(key, binop, seq, init):
for item in seq:
k = key(item)
if k not in d:
d[k] = init
if init is no_default:
d[k] = item
continue
else:
d[k] = init
d[k] = binop(d[k], item)
return d

Expand Down
4 changes: 4 additions & 0 deletions toolz/tests/test_itertoolz.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,10 @@ def test_reduceby():
projects, 0) == {'CA': 1200000, 'IL': 2100000}


def test_reduce_by_init():
assert reduceby(iseven, add, [1, 2, 3, 4]) == {True: 2 + 4, False: 1 + 3}


def test_iterate():
assert list(itertools.islice(iterate(inc, 0), 0, 5)) == [0, 1, 2, 3, 4]
assert list(take(4, iterate(double, 1))) == [1, 2, 4, 8]
Expand Down