Multikey Dict?

Bengt Richter bokr at oz.net
Sun Nov 13 18:12:51 EST 2005


On Sun, 13 Nov 2005 01:03:05 +0100, David Rasmussen <david.rasmussen at gmx.net> wrote:

>If I have a collection of dicts like:
>
>john = {'id': 1, 'name': "John Cleese", 'year': 1939}
>graham = {'id': 2, 'name': "Graham Chapman", 'year': 1941}
>
Why do you use dicts for what looks like fixed-format records? Why not just tuples? E.g.,
 john = (1, "John Cleese", 1939)
 graham = (2, "Graham Chapman", 1941)


>I could store all of them in a list. But for easy lookup, I might store 
>all these in a dict instead, like
>
>people = {'1': john, '2': graham}
>
>or maybe
>
>people = {'John Cleese': john, 'Graham Chapman': graham}
>
>or whatever key I might choose. Now, first of all, it seems a bit 
>annoying that I have to keep that redundant data in the second dict that 
ISTM you are confusing equivalent references with redundant data. The
people dict does not "contain" its own copy of john and graham objects,
it just refers to them, and you get to look up the reference by key name.

>is already in the individual dicts within people. Secondly (and this is 
>my question), it is annoying that I have to choose one of several 
>unambiguous keys as a key.
Keys in the same dict have to be unambiguous, or how could you retrieve
an associated value?

>
>I would like to be able to say:
>
>people['1'].year
>
>in some case and in other cases I want to say
>
>people['John Cleese'].year
>
>That is, sometimes I have the name at hand and would like to look up 
>data based on that. Other times, I have the ID at hand and would like to 
>look up data based on that instead.
No prob. So long as no one has a name like '1' or an id like 'John Cleese'
you can keep both '1':john and 'John Cleese':john  key:value associations
in the same dict. Referring to the same value with different keys is no prob.

Of course, using tuples for john and graham you can't get year as an attribute.
Recalling from above
    john = (1, "John Cleese", 1939)

you'd have to write
    people['1'][2]
or
    people['John Cleese'][2]

Or you could define some handy mnemonic constants to match the tuple, e.g.,
    ID, NAME, YEAR = range(3)

and then you could write
    people['1'][YEAR]
or
    people['John Cleese'][YEAR]

Or you could define an object giving you the attribute access you wanted.
Not as efficient spacewise though, unless you define __slots__.

Of course, you can use dicts for john and graham if you need the ability
to add arbitrary fields. If this happens rarely, you could conceivably gain
efficiency in storage by using slots for the normal data and a single slot
initialized to None for extra data, and then create a dict for that slot
only if you need to extend with new field names.

>
>Also, I would like if I didn't have to keep the key data both in the 
>dict of dicts and in the dicts :)
IIUC I guess you don't have to.
>
>If I could just say to Python: john and graham (and ...) are all a part 
>of a "superdict" and either their id or their name can be used as keys.
>
>Can I do that somehow?
Sure. What API would you like for your superdict?
Defining requirements is usually the hardest part, because newbies
often imagine limitations that don't exist in Python ;-)

Others will have proposed many variants by now, I assume ;-)

Regards,
Bengt Richter



More information about the Python-list mailing list