Sohaib Farooqi
Sohaib Farooqi

Reputation: 5676

Filter list of dict based on values from another dict

I have a list of dictionaries list_of_dict, a set of keys set_of_keys and another dictionary dict_to_compare.

I need to filter the list of dicts if the values of any two of the three possible keys matches the values from dict_to_compare.

Input:

set_of_keys = {'val1', 'val2', 'val3'}

dict_to_compare = {'k1': 'val1', 'k2': 'val2','k3':'val6'}

list_of_dict = [
        {'k1': 'val1', 'k2': 'val2', 'k3':'val3'},
        {'k1': 'val4', 'k2': 'val5', 'k3':'val6'},
        {'k1': 'val7', 'k2': 'val8', 'k3':'val9'}
]

Output:

 out = [{'k1': 'val1', 'k2': 'val2', 'k3': 'val3'}] #First element from list

I tried doing this by explicitly specifying bunch of if elif conditions. But the problem is set of keys is really huge. Is there a better way to solve this?

Thanks

Upvotes: 9

Views: 1917

Answers (4)

Abhijith Asokan
Abhijith Asokan

Reputation: 1875

My answer is similar to most of the answers here.

I would suggest you to use custom function that stops comparing keys when desired match count is achieved. Since you mentioned you have a lot of keys to compare, this would be beneficial.

def my_sum(gen,count_needed):
    for e in gen:                 #gen is a generator
        if e:                     #e is true when keys match
            count_needed -= 1
            if count_needed==0:   #stop comparison when desired no.of matches is found
                return True
    return False


count_needed = 2
out = [ d for d in list_of_dict
        if my_sum( (d[key] == dict_to_compare[key] for key in d) ,count_needed) 
]

Upvotes: 1

Ma0
Ma0

Reputation: 15204

You can recreate the list_of_dict using a list-comprehension that features your desired filtering scheme:

set_of_keys = {'val1', 'val2', 'val3'}

dict_to_compare = {'k1': 'val1', 'k2': 'val2','k3':'val6'}

list_of_dict = [
        {'k1': 'val1', 'k2': 'val2', 'k3':'val3'},
        {'k1': 'val4', 'k2': 'val5', 'k3':'val6'},
        {'k1': 'val7', 'k2': 'val8', 'k3':'val9'}
]

list_of_dict = [d for d in list_of_dict if sum(1 for k, v in d.items() if dict_to_compare.get(k, None)==v)>1]
print(list_of_dict)  # -> [{'k1': 'val1', 'k2': 'val2', 'k3': 'val3'}]

Upvotes: 5

Ajax1234
Ajax1234

Reputation: 71481

You can use sum:

dict_to_compare = {'k1': 'val1', 'k2': 'val2','k3':'val6'}
set_of_keys = {'val1', 'val2', 'val3'}
list_of_dict = [
    {'k1': 'val1', 'k2': 'val2', 'k3':'val3'},
    {'k1': 'val4', 'k2': 'val5', 'k3':'val6'},
    {'k1': 'val7', 'k2': 'val8', 'k3':'val9'}
]
final_list = [i for i in list_of_dict if sum(c in set_of_keys for c in i.values()) >= 2]

Output:

[{'k3': 'val3', 'k2': 'val2', 'k1': 'val1'}]

Upvotes: 8

zipa
zipa

Reputation: 27899

I don't know if I understood what you need, but this is my shot:

result = [i for i in list_of_dict if len([j for j in i.values() if j in dict_to_compare.values()]) == len(set_of_keys) - 1]

Upvotes: 1

Related Questions