How to compare values of two dictionaries with list comprohension?

1.1k views Asked by At

How to compare only the values of two dictonaries?

So I have this:

dict1 = {"appe": 3962.00, "waspeen": 3304.08}
dic2 = {"appel": 3962.00, "waspeen": 3304.08}


def compare_value_dict(dic):
    return dic

def compare_value_dict2(dic2):   
    return dic2
    

def compare_dic(dic1, dic2):
    if dic1 == dic2:       
        print('the same dictionary')
    else:      
        print('difference dictionary')

compare_dic(compare_value_dict(dict1).values(), compare_value_dict2(dic2.values()))

this works:

compare_dic(compare_value_dict(dict1).keys(), compare_value_dict2(dic2.keys()))
4

There are 4 answers

0
Sardar Faisal On

Good theory explanation give by @Martijn post. Here is a simple way to compare 2 dict values if they are having same keys:

difference = [k for k, v in dict1.items() if v != dict2[k]]

To compare only the similar keys they the dict instance are from different dicts:

difference = [k for k, v in dict1.items() if k in dict2 and v != dict2[k]]

The returned difference list contains the different key not the values. In order to have value simply switch the first k with v

Second method is utilizing sets:

set1 = set(dict1.items())
set2 = set(dict2.items())
set1 ^ set2
1
David Rura On

you can go with the function dic.keys() that returns a vector containing all "headers" from your dictionary. And in the for loop, you can compare.

8
Martijn Pieters On

You can't use == on the dict.values() dictionary view objects, as that specific type doesn't act like a set. Instead values_view_foo == values_view_bar is only ever true if both refer to the same dictionary view object. The contents don't matter.

It'll depend entirely on the types of values that the dictionary contains on what techniques can be used here. The following options will cover many different types of values, but not all. It is not really possible to make a generic one-size-fits-all comparison function for all possible types of values in a dictionary.

In this specific case, you can turn your values views into sets, because the values happen to both be unique and hashable:

def compare_dict_values(dv1, dv2):
    """Compare two dictionary values views

    Values are assumed to be unique and hashable

    """
    return set(dv1) == set(dv2)

Where the values are not unique, and / or not hashable, you'll have to find another way to compare the values.

If they are, say, sortable (orderable), then you could compare them by first sorting the values:

def compare_dict_values(dv1, dv2):
    """Compare two dictionary value views

    Values are assumed to be orderable, but do not need to be unique
    or hashable.

    """
    return len(dv1) == len(dv2) and sorted(dv1) == sorted(dv2)

By sorting you remove the issue with the values view being unordered. The len() check is there because it is much cheaper than sorting and so let’s you avoid the sort when it is not necessary.

If the values are hashable but not unique (and so the values collection ('foo', 'bar', 'foo') is different from ('foo', 'bar', 'bar')), you can use Counter() objects to capture both the values and their counts:

from collections import Counter

def compare_dict_values(dv1, dv2):
    """Compare two dictionary value views

    Values are assumed to be hashable, but do not need to be unique.

    """
    return Counter(dv1) == Counter(dv2)

Note: Each of these techniques assume that the individual values in the dictionary support equality testing and you only need them to be exactly equal. For floating point values, you can run into issues where the values are almost equal, but not exactly equal. If your values need to be close and not just exactly equal, you can use the math.isclose() function on each pair of values. Use zip(sorted(dv1), sorted(dv2)) to pair up the values:

def float_dict_values_close(dv1, dv2, **kwargs):
    """Compare two dictionary view objects with floats

    Returns true if the values in both dictionary views are
    *close* in value.

    """
    if len(dv1) != len(dv2):
        return False
    v1, v2 = sorted(dv1), sorted(dv2)
    return all(is_close(*vs, **kwargs) for vs in zip(v1, v2))

Things get more complicated if your values can be different types; you generally can't sort a dictionary values view with a mix of different types in it. If you have a mix of types where not all the types are hashable, you'd have to separate out the different types first and then use a mixture of techniques to compare the values of the same type. This gets complicated when you have a hierarchy of types where subclasses can be compared with superclasses, etc. I'm declaring that as outside the scope of this answer.

3
Alibederchi On

so you wanna check if your dictionaries are same with their values right?

dict1 = {"appe": 3962.00, "waspeen": 3304.08}
dic2 = {"appel": 3304.08, "waspeen": 3962.00}
def comparision(*dicts):
    instanceToCompare , values = len(dicts[0].values()) , set()
    for d in dicts:
        for value in d.values():
            values.add(value)
    return True if len(values) == instanceToCompare else False
print('all dictionaries has same values') if comparision(dict1 , dic2) else 
print('input dictionaries are not same at all')

you'll know if all values in dictionaries are same or not , regardless to their order or repitation