evalinia
evalinia

Reputation: 13

python: find matching values in nested dictionary

I'm new to python dictionaries as well as nesting.

Here's what I'm trying to find - I have objects that all have the same attributes: color and height. I need to compare all the attributes and make of list of all the ones that match.

matchList = []
dict = {obj1:{'color': (1,0,0), 'height': 10.6},
        obj2:{'color': (1,0.5,0), 'height': 5},
        obj3:{'color': (1,0.5,0), 'height': 5}, 
        obj4:{'color': (1,0,0), 'height': 10.6}}

I need to find a way to compare each of the objs to one another and create a nested list of all the ones that match. So if obj1 and obj4 match, and obj2 & 3 match, I want this is my result:

matchList = [[obj1, obj4], [obj2, obj3]]

How would I go about doing this?

Upvotes: 1

Views: 4340

Answers (2)

satoru
satoru

Reputation: 33215

dict refers to the built-in Python dictionary class, so you'd better not override it.

I've renamed the dictionary to objs in the following example:

import itertools as it
keys = sorted(objs.keys(), key=lambda k: objs[k]) # Make sure `objs` with the same value be arranged next to each other
groups = it.groupby(keys, lambda k: d[k]) # so that we can group them by value
match_list = [list(keys) for v, keys in groups]

Upvotes: 1

abarnert
abarnert

Reputation: 365667

What you're looking to do is to create equivalence classes of the values.

Normally, this is easy: just reverse the dict into a multidict (a dict whose values are sets or lists of 0 or more actual values), and then each set or list of values is an equivalent class:

original_dict = {'a': 1, 'b': 2, 'c': 1, 'd': 2}

from collections import defaultdict
reverse_multidict = defaultdict(list)
for key, value in original_dict.items():
    reverse_multidict[value].append(key)

matchList = list(reverse_multidict.values()) # leave out the list() in 2.x

However, in your case, the values are dicts, which means they can't be used as keys in a dict.

The simplest way around that is to transform each dict into something that's immutable and hashable, like a tuple of key-value tuples:

for key, value in original_dict.items():
    reverse_multidict[tuple(value.items())].append(key)

Upvotes: 1

Related Questions