expression form of one-to-many dict?
Robert Brewer
fumanchu at amor.org
Fri Dec 17 17:07:57 EST 2004
Steven Bethard wrote:
> So I end up writing code like this a fair bit:
>
> map = {}
> for key, value in sequence:
> map.setdefault(key, []).append(value)
>
> This code basically constructs a one-to-many mapping -- each
> value that
> a key occurs with is stored in the list for that key.
>
> This code's fine, and seems pretty simple, but thanks to generator
> expressions, I'm getting kinda spoiled. ;) I like being able to do
> something like the following for one-to-one mappings:
>
> dict(sequence)
>
> or a more likely scenario for me:
>
> dict((get_key(item), get_value(item) for item in sequence)
>
> The point here is that there's a simple sequence or GE that I
> can throw
> to the dict constructor that spits out a dict with my
> one-to-one mapping.
>
> Is there a similar expression form that would spit out my one-to-many
> mapping?
Given:
class Chain(dict):
"""Behaves like a dictionary, but setting a value adds it to a list
instead of replacing the existing value.
Retrieving a value always returns the first such value. If you want
all such values, call Chain.chain(key) instead.
Deleting an item removes the entire list for that key.
"""
def __init__(self, initialValues={}):
for key, value in initialValues.items():
self[key] = value
def __getitem__(self, key):
return dict.__getitem__(self, key)[0]
def __setitem__(self, key, value):
self.setdefault(key, []).insert(0, value)
def get(self, key, default=None):
try:
return dict.__getitem__(self, key)[0]
except KeyError:
return default
def update(self, newDict):
for key, value in newDict.items():
self[key] = value
def items(self):
return [(key, val[0]) for key, val in dict.items(self)]
def values(self):
return [val[0] for val in dict.values(self)]
def iteritems(self):
for key, val in dict.iteritems(self):
yield (key, val[0])
def itervalues(self):
for val in dict.itervalues(self):
yield val[0]
def chain(self, key):
"""Return all values of a given key in a list."""
try:
return dict.__getitem__(self, key)
except KeyError:
return []
def iterchains(self):
"""C.iterchains() -> an iterator over the (key, chain) pairs of
C."""
return dict.iteritems(self)
...the one-liners flow effortlessly. ;)
Robert Brewer
MIS
Amor Ministries
fumanchu at amor.org
More information about the Python-list
mailing list