reverse dict lookup & Relation class
Aaron Brady
castironpi at gmail.com
Sat Jan 17 03:24:21 EST 2009
On Jan 16, 5:03 am, Steven D'Aprano <st... at REMOVE-THIS-
cybersource.com.au> wrote:
> On Wed, 14 Jan 2009 16:30:36 -0800, Aaron Brady wrote:
> > Hi, this is a continuation of something that comes up now and again
> > about reverse lookups on dictionaries, as well as a follow-up to my
> > pursuit of a Relation class from earlier.
>
> [...]
>
> > What's the best way to construct this class? Or, do you have an
> > argument that it could not be simpler than using a relational db?
> > Brainstorming, not flamestorming.
>
> Here's a lightweight solution that uses lazy calculation of the reverse
> dict. It makes a number of assumptions:
>
> - both keys and values will be hashable and unique;
> - the dict won't be so large that calculating the reverse dictionary will
> be time consuming;
> - modifications to instance.reverse are undefined.
>
> Usage:
>
> >>> d = ReverseDict(x=2, y=3, z=4)
> >>> d['x']
> 2
> >>> d.reverse[2]
> 'x'
> >>> d['a'] = 0
> >>> d.reverse[0]
>
> 'a'
>
> def make_dirty(func):
> from functools import wraps
> @wraps(func)
> def f(self, *args, **kwargs):
> self._dirty = True
> return func(self, *args, **kwargs)
> return f
>
> # only tested a little bit
> class ReverseDict(dict):
> def __init__(self, *args, **kwargs):
> super(ReverseDict, self).__init__(*args, **kwargs)
> self._dirty = True
> @make_dirty
> def clear():
> super(ReverseDict, self).clear()
snip
> @property
> def reverse(self):
> if self._dirty:
> # Modify this to support repeated and non-hashable values.
> self._reverse = dict((value, key) for
> (key, value) in self.iteritems())
> self._dirty = False
> return self._reverse
>
> An even more lightweight solution is to give up O(1) for the reverse
> lookup:
>
> # untested
> class ReversableDict(dict):
> def lookupvalue(self, value):
> for k,v in self.iteritems():
> if v == value: return k
> raise ValueError('value not found')
> def lookupallvalues(self, value):
> results = []
> for k,v in self.iteritems():
> if v == value: results.append(k)
> return results
>
> --
> Steven
Can you make it work for a 3-way lookup?
More information about the Python-list
mailing list