Doing set operation on non-hashable objects

5lvqbwl02 at sneakemail.com 5lvqbwl02 at sneakemail.com
Sun Dec 28 03:54:51 EST 2008


On Dec 24, 12:21 pm, "Gabriel Genellina" <gagsl-... at yahoo.com.ar>
wrote:
> En Wed, 24 Dec 2008 17:16:59 -0200, <5lvqbw... at sneakemail.com> escribió:
>
> > I'm writing an application which is structured roughly as follows:
>
> > "db" is a dict, where the values are also dicts.
> > A function searches through db and returns a list of values, each of
> > which is a dict as described above.
> > I need to perform set operations on these lists (intersection and
> > union)
> > However the objects themselves are not hashable, and therefore can't
> > be in a set, because they are dicts.
>
>
> If you *only* care about object identity, you might use a dictionary that  
> only compares by identity to anyone else:
>
> class nc_dict(dict):
>    "A hashable dictionary that isn't equal to anyone else"
>
>    def __eq__(self, other):
>      return cmp(id(self),id(other))==0
>
>    def __hash__(self):
>      return hash(id(self))
>
> d1 = nc_dict(a=1, b=2, c=3)
> d2 = nc_dict(b=2, c=0, d=4)
> d3 = nc_dict(a=1, c=3, e=5)
> dd1 = nc_dict(x=d1, y=d2)
> dd2 = nc_dict(x=d1, y=d3)
> dd3 = nc_dict(y=d2, z=d3, w=d1)
> l1 = [dd1, dd2]
> l2 = [dd2, dd3]
> s1 = set(l1)
> s2 = set(l2)
> print s1-s2
> print s2-s1
> print s1&s2
>
> # instances of nc_dict with the same contents are NOT equal
> d4 = nc_dict(a=1, b=2, c=3)
> print d1, d4, d1==d4  # output: False
>
> # but we can use this function to compare contents
> def cmp_contents(d1, d2):
>      try: return cmp(sorted(d1.items()), sorted(d2.items()))
>      except Exception: return 1 # assume they're unequal
>
> print cmp_contents(d1,d4)==0 # output: True

Good idea.   I'll try this out.  I don't think it's likely that I'll
have a case where the dicts have identical values, but different
identities.  And if they do I probably don't care too much.

Thanks







More information about the Python-list mailing list