Comparing Multiple Dictionaries With Specific Values - python

I have four dictionaries of similar length.
I want to:
get those keys that are matched between the four.
Iterate over certain value in each dictionary which I will compare later and do some arithmetic operations.
I have done that using nested loop (four loops) but that doesn't look efficient at all. I want to make this code more efficient and elegant.
I want to do that without doing nested loop:
d1 = {1:18:[['28','Y','N'],['108','A','M'],...]
d2,d3 and d4 are the same thing expect different values but some will have same keys
for k, v in di1.iteritems():
for v1 in v:
for k2,v2 in di2.iteritems():
for va2 in v2:
if k == k2:
for k3,v3 in di3.iteritems():
for va3 in v3:
if k2 == k3:
for k4,v4 in di4.iteritems():
for va4 in v4:
if k3==k4 and k==k4 and k==k3:
# do some arithmetics on dictionary's values for all four dictionaries
Thanks a lot in advance.

if they have the same keys, then di1.keys() == di2.keys() == di3.keys() == di4.keys().
keys = di1.keys()
for k in keys:
# do something with di1[k] di2[k] di3[k] di4[k]
if they do not all have the keys, build the union set of the keys, and check which dict has each key, using in:
keys = set(di1.keys()) | set(di2.keys()) | set(di3.keys()) | set(di4.keys())
for k in keys:
if k in di1:
# di1 has the key
if k in di2:
# di2 has the key
if k in di1 and k in di2:
# do something with di1[k] and di2[k]
# ...

1) I assume "get those keys that are matched between the four" means you want to find keys that are present in ALL four dictionaries. One way to achieve this is to take the intersection of the four sets of keys.
common_keys = set(d1.keys()) & set(d2.keys()) & set(d3.keys()) & set(d4.keys())
2) Iterate over the common keys and "do some arithmetics on dictionary's values for all four dictionaries":
for key in common_keys:
for dict in [d1, d2, d3, d4]:
# do something with dict[key]...
You can also use list comprehensions if you wish to avoid nested loops, e.g. generate a list of (key, list of tuples) pairs and operate on that later:
common_keys_vals = [(key, [dict[key] for dict in [d1, d2, d3, d4]])
for key in common_keys]

Related

filter a dictionary by key less than some range of values

I have a dictionary like this,
d = {1:'a', 2:'b', 3:'c', 4:'d'}
Now I want to filter the dictionary where the key should be more than 1 and less than 4 so the dictionary will be,
d = {2:'b', 3:'c'}
I could do this using a for loop, iterating over all the keys. but the execution time will be more looking for some fastest way to do this more efficiently in pythonic way.
you can try below code:
d = {k:v for k,v in d.items() if 1<k<4}
Pythonic way would be to use a dictionary comprehension:
{key: value for key, value in d.items() if 1 < key < 4}
It's readable enough: for each key and value in the items of the dictionary, keep those key: value pairs that have their keys between 1 and 4.
More pythonic way would be a dictionary comprehension
d = {k: v for (k, v) in d.items() if k > 1 and k < 4}
If the efficiency is a bottleneck, you may want to try to use some tree based structure instead of a dictionary that is hash based.
Python dictionaries use hashes of their keys to efficiently lookup and store data. Unfortunately, that means that they don't allow you use the numeric properties of those keys to select data (the way you might be able to do using a slice to index a list).
So I think the best way to do what you want is probably just a dictionary comprehension that tests each key against your boundary values:
d = {key: value for key, value in d.items() if 1 < key < 4}

Join two keys and corresponding values in a list with a character

I have two lists, say
x = [{'name':'sri'}], y= [{'job':'nothing'}]
I want to join the two keys into one key and the values into one value, say
z = [{'name/job':'sri/nothing'}]
I have tried the following
z = x.update(y[0])
z[0:1] = ["/".join(z[0:1])]
but it shows list doesnot have update attribute error.
I have tried to combine two lists like
z = x+y
# z=[{'name':'sri'},{'job':'nothing'}]
and tried to combine keys, but couldn't find a solution
Note: x and y always have only key-value pair respectively.
You need to use zip() to pair up your dictionaries, then pair up the key-value pairs in each to generate output dictionaries:
result = [
{'{}/{}'.format(k1, k2): '{}/{}'.format(v1, v2) for (k1, v1), (k2, v2) in zip(d1.items(), d2.items())}
for d1, d2 in zip(x, y)
]
Demo:
>>> x = [{'name': 'sri'}]
>>> y = [{'job': 'nothing'}]
>>> [
... {'{}/{}'.format(k1, k2): '{}/{}'.format(v1, v2) for (k1, v1), (k2, v2) in zip(d1.items(), d2.items())}
... for d1, d2 in zip(x, y)
... ]
[{'name/job': 'sri/nothing'}]
The above list and dict comprehension combination essentially does this:
result = []
for d1, d2 in zip(x, y):
# d1 and d2 are a pair of dictionaries from lists x and y, respectively.
newdict = {}
for (k1, v1), (k2, v2) in zip(d1.items(), d2.items()):
# k1 and v1 are a key-value pair from d1, and
# k2 and v2 are a key-value pair from d2. This loop runs just once
# when your input dictionaries have only one key-value each.
key = '{}/{}'.format(k1, k2) # new key with k1/k2 combined
value = '{}/{}'.format(v1, v2) # new value with v1/v2 combined
newdict[key] = value
result.append(newdict)
but without the intermediate variables.
The solution assumes that x and y consist of an equal number of dictionaries (any extra elements in one of the lists will be ignored). Each dictionary pair is assumed to have the same number of key-value pairs (again, extra key-value pairs in one dictionary will be ignored), and the key-value pairs of any dictionary pair are combined in current dictionary order. For dictionaries with only a single key each that order doesn’t matter.
You can use a small loop and then formatted strings for your keys and values
z = {}
for k, v in x.items():
for a, b in y.items():
z['{}/{}'.format(k, a)] = '{}/{}'.format(v, b)
{'name/job': 'sri/nothing'}

how to find common keys from two dict with difference in values

I am trying to get the keys whose values differ in both dictionaries
e.g:
items1=['a','b','c']
price1=[1,2,3]
dictA= dict(zip(items1, price1))
items2=['a','b']
price2=[1,3]
dictB=dict(zip(items2,price2))
so the difference will be ['b'] as this key is the only difference
i tried using set(dictA.items()).symmetric_difference(dictB.items()), but this is also returning the key:value {'c':3}
Iterate over the common keys, and drop keys having matching values in dictA and dictB:
In [3]: {key for key in dictA.keys() & dictB if dictA[key] != dictB[key]}
Out[3]: {'b'}
You'll have to iterate over the intersection.
delta = [k for k in (set(dictA) & set(dictB)) if (dictB[k] - dictA[k])]

Refactoring with python dictionary comprehension

I have 2 dictionary which contain the same keys but the value pairs are different. Let's make dictA and dictB represent the two dictionaries in question.
dictA = {'key1':'Joe', 'key2':'Bob'}
dictB = {'key1':'Smith', 'key2':'Johnson'}
Currently, I am creating a new dictionary based the common occurring keys through a nested if statement. In doing so, the values that share a key are contained within a list, in the new dictionary. See this done below:
dictAB = {} # Create a new dictionary
# Create a list container for dictionary values
for key in dictA.keys():
dictAB[key] = []
# Iterate through keys in both dictionaries
# Find matching keys and append the respective values to the list container
for key, value in dictA.iteritems():
for key2, value2 in dictB.iteritems():
if key == key2:
dictAB[key].append(value)
dictAB[key].append(value2)
else:
pass
How can this be made into a more clean structure using python dictionary comprehension?
Use sets or key views (python 2.7):
dictAB = {k: [dictA[k], dictB[k]] for k in dictA.viewkeys() & dictB.viewkeys()}
Before 2.7:
dictAB = dict((k, [dictA[k], dictB[k]]) for k in set(dictA) & set(dictB))
In python 3, you can use the .keys method for such operations directly, as they are implemented as views:
dictAB = {k: [dictA[k], dictB[k]] for k in dictA.keys() & dictB.keys()}
Demo (python 2.7):
>>> dictA = {'key1':'Joe', 'key2':'Bob'}
>>> dictB = {'key1':'Smith', 'key2':'Johnson'}
>>> dictAB = {k: [dictA[k], dictB[k]] for k in dictA.viewkeys() & dictB.viewkeys()}
>>> print dictAB
{'key2': ['Bob', 'Johnson'], 'key1': ['Joe', 'Smith']}
The & operator on either two sets or on a dict view creates the intersection of both sets; all keys that are present in both sets.
By using an intersection of the keys, this code will work even if either dictA or dictB has keys that do not appear in the other dictionary. If you are absolutely sure the keys will always match, you could just iterate over either dict directly without the intersection:
dictAB = {k: [dictA[k], dictB[k]] for k in dictA}
dictAB = { key: [dictA[key],dictB[key]] for key in dictA if key in dictB }

Duplicates in a dictionary (Python)

I need to write a function that returns true if the dictionary has duplicates in it. So pretty much if anything appears in the dictionary more than once, it will return true.
Here is what I have but I am very far off and not sure what to do.
d = {"a", "b", "c"}
def has_duplicates(d):
seen = set()
d={}
for x in d:
if x in seen:
return True
seen.add(x)
return False
print has_duplicates(d)
If you are looking to find duplication in values of the dictionary:
def has_duplicates(d):
return len(d) != len(set(d.values()))
print has_duplicates({'a': 1, 'b': 1, 'c': 2})
Outputs:
True
def has_duplicates(d):
return False
Dictionaries do not contain duplicate keys, ever. Your function, btw., is equivalent to this definition, so it's correct (just a tad long).
If you want to find duplicate values, that's
len(set(d.values())) != len(d)
assuming the values are hashable.
In your code, d = {"a", "b", "c"}, d is a set, not a dictionary.
Neither dictionary keys nor sets can contain duplicates. If you're looking for duplicate values, check if the set of the values has the same size as the dictionary itself:
def has_duplicate_values(d):
return len(set(d.values())) != len(d)
Python dictionaries already have unique keys.
Are you possibly interested in unique values?
set(d.values())
If so, you can check the length of that set to see if it is smaller than the number of values. This works because sets eliminate duplicates from the input, so if the result is smaller than the input, it means some duplicates were found and eliminated.
Not only is your general proposition that dictionaries can have duplicate keys false, but also your implementation is gravely flawed: d={} means that you have lost sight of your input d arg and are processing an empty dictionary!
The only thing that a dictionary can have duplicates of, is values. A dictionary is a key, value store where the keys are unique. In Python, you can create a dictionary like so:
d1 = {k1: v1, k2: v2, k3: v1}
d2 = [k1, v1, k2, v2, k3, v1]
d1 was created using the normal dictionary notation. d2 was created from a list with an even number of elements. Note that both versions have a duplicate value.
If you had a function that returned the number of unique values in a dictionary then you could say something like:
len(d1) != func(d1)
Fortunately, Python makes it easy to do this using sets. Simply converting d1 into a set is not sufficient. Lets make our keys and values real so you can run some code.
v1 = 1; v2 = 2
k1 = "a"; k2 = "b"; k3 = "c"
d1 = {k1: v1, k2: v2, k3: v1}
print len(d1)
s = set(d1)
print s
You will notice that s has three members too and looks like set(['c', 'b', 'a']). That's because a simple conversion only uses the keys in the dict. You want to use the values like so:
s = set(d1.values())
print s
As you can see there are only two elements because the value 1 occurs two times. One way of looking at a set is that it is a list with no duplicate elements. That's what print sees when it prints out a set as a bracketed list. Another way to look at it is as a dict with no values. Like many data processing activities you need to start by selecting the data that you are interested in, and then manipulating it. Start by selecting the values from the dict, then create a set, then count and compare.
This is not a dictionary, is a set:
d = {"a", "b", "c"}
I don't know what are you trying to accomplish but you can't have dictionaries with same key. If you have:
>>> d = {'a': 0, 'b':1}
>>> d['a'] = 2
>>> print d
{'a': 2, 'b': 1}

Categories

Resources