Grouping items with a key?

It seems to me that Python should have a built-in module for this. Take a list of items and translate them into a dictionary that matches keys with a list of items with a shared key.

This is easy enough to do:

# using defaultdict
lookup = collections.defaultdict(list)
for item in items:
    lookup[key(item)].append(item)

# or, using plain dict
lookup = {}
for item in items:
    lookup.setdefault(key(item), []).append(item)

But it is often enough to use that the built-in function will be enjoyable. I could implement it myself, as such:

def grouped(iterable, key):
    result = {}
    for item in iterable:
        result.setdefault(key(item), []).append(item)
    return result

lookup = grouped(items, key)

This differs from itertools.groupbyseveral important ways. To get the same result from groupby, you will need to do this, which is a little ugly:

lookup = dict((k, list(v)) for k, v in groupby(sorted(items, key=key), key))

Some examples:

>>> items = range(10)
>>> grouped(items, lambda x: x % 2)
{0: [0, 2, 4, 6, 8], 1: [1, 3, 5, 7, 9]}

>>> items = 'hello Qaru how are you'.split()
>>> grouped(items, len)
{8: ['overflow'], 3: ['how', 'are', 'you'], 5: ['hello', 'stack']}

Is there a better way?

+5
source share
2 answers

comp.lang.python, , , , , . . , .

# using defaultdict
lookup = collections.defaultdict(list)
for item in items:
    lookup[key(item)].append(item)

# or, using plain dict
lookup = {}
for item in items:
    lookup.setdefault(key(item), []).append(item)

, , - , .

+3

- API, groupby, :

def groupby2(iterable, keyfunc):
    lookup = collections.defaultdict(list)
    for item in iterable:
        lookup[keyfunc(item)].append(item)
    return lookup.iteritems()

, , , , iteritems , .

+1

All Articles