3

I find myself frequently making indexed lists from flat ones in Python. This is such a common task that I was wondering if there's a standard utility that I should be using for it.

The context is this: given an array, I need to create a dict of smaller arrays using some key for grouping.

e.g:
["Andy","Alice","Bob","Beth","Charlie"] becomes
{"A":["Andy","Alice"],"B":["Bob","Beth"],"C":["Charlie"]}

My solution looks like this:

def make_index(data,key,value=lambda x:x):
    d={}
    for item in data:
        k = key(item)
        v = value(item)
        try: d[k].append(v)
        except KeyError: d[k]=[v]
    return d

It's simple and all, but am I reinventing something that is implemented better elsewhere?

2 Answers 2

5

You can do the same a little simpler with a defaultdict:

from collections import defaultdict

def make_index(data,key,value=lambda x:x):
    d=defaultdict(list)
    for item in data:
        d[key(item)].append(value(item))
    return d

Using a defaultdict is faster than using .setdefault(), which would be the other option.

Sign up to request clarification or add additional context in comments.

1 Comment

@JoranBeasley: it's the sorting you do that kills it.
3

Not sure why the itertools answer was deleted, but I was writing one myself:

from itertools import groupby
def make_index(data, key = lambda x: x[0]):
    return {key: list(gr) for key, gr in 
        groupby(sorted(data, key=key), key=key)}

In [3]: make_index(["Andy","Alice","Bob","Beth","Charlie"])
Out[3]: {'A': ['Andy', 'Alice'], 'B': ['Bob', 'Beth'], 'C': ['Charlie']}

In [4]: make_index(["Andy","Alice","Bob","Beth","Charlie"], key=lambda x: len(x))
Out[4]: {3: ['Bob'], 4: ['Andy', 'Beth'], 5: ['Alice'], 7: ['Charlie']}

2 Comments

This is certainly a more interesting answer, but it appears to take about twice as much time as Martijn's version, probably because it's mult-step transform.
@tylerl Yeah, Martjijn's version doesn't need to sort the list.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.