Subtraction if an items matches in both dictionaries working wrong - python

I have two dictionaries and I want to subtract value of an item if found in both the dictionaries for which I am doing this:
My Code:
X = {'a':7, 'b':8,'c':9,'d':10}
Y = {'a':3, 'b':4,'c':9}
res = {}
for k,v in X.items():
for m,n in Y.items():
if k == m:
res[k] = v-n
else:
res[k] = v
It is giving me output:
res = {'a': 7, 'b': 8, 'c': 0, 'd': 10}
whereas what I need is this:
res = {'a': 4, 'b': 4, 'c': 0, 'd': 10}
How can I get that ? And also why the above code isn't working ?

insert break statement in 1st condition as below:
X = {'a':7, 'b':8,'c':9,'d':10}
Y = {'a':3, 'b':4,'c':9}
res = {}
for k,v in X.items():
for m,n in Y.items():
if k == m:
res[k] = v-n
break
else:
res[k] = v
print(res)

You can try this.
{k:X.get(k,0)-Y.get(k,0) for k in X.keys()|Y.keys()}
# {'a': 4, 'b': 4, 'c': 0, 'd': 10} -->Order will not be maintained

Related

How to get maximum values of all the keys in the list of dictonary

I am facing an issue with getting the maximum of each key in an list of dictionary.
for example I have a list of dictionaries ls:
ls = [{'a':2, 'b':4, 'c':7}, {'a':5, 'b': 2, 'c':6}, {'a':1, 'b': 3, 'c':8}]
The output should be {a = 5, b = 4, c = 8}
I have tried a number of methods, for example:
maxx= max(ls, key=lambda x:x['a'])
but this and every other method is returning me the sub-dictonary having the maximum "a" value, b and c is not getting considered
can anyone please help me out on this
Assuming all your dictionaries have the same keys:
{k: max(d[k] for d in ls if k in d) for k in ls[0].keys()}
outputs {'a': 5, 'b': 4, 'c': 8}
I use the keys of the first dictionary ls[0], supposed to be the same as the others
If your dictionaries don't have the same keys, here is a one liner solution
(Thank you #Timus for the improvements in the comments)
{k: max(d[k] for d in ls) for k in set().union(*(d.keys() for d in ls)) }
set().union(*(d.keys() for d in ls)) concatenates all keys and select the set of unique keys.
max(d[k] for d in ls if k in d) just select the max value if the key is in the dict.
Maybe there is a more elegant solution, but this one works:
ls = [{'a':2, 'b':4, 'c':7}, {'a':5, 'b': 2, 'c':6}, {'a':1, 'b': 3, 'c':8}]
#initialize with first dict
final_dict = ls[0]
for mydict in ls:
if mydict['a']>final_dict['a']:
final_dict['a'] = mydict['a']
if mydict['b']>final_dict['b']:
final_dict['b'] = mydict['b']
if mydict['c']>final_dict['c']:
final_dict['c'] = mydict['c']
print(final_dict)
Not elegant solution, but small.
keys = ls[0].keys()
res = dict()
for key in keys:
maxvalue = max(ls, key=lambda x:x[key])
res[key] = maxvalue[key]
-> {'a': 5, 'b': 4, 'c': 8}
This get the work done
maxii = {}
for item in ls:
for key, value in item.items():
if key not in maxii:
maxii[key] = value
else:
maxii[key] = max(maxii[key], value)
Create an empty output dictionary then iterate over the remaining items:
ls = [{'a':2, 'b':4, 'c':7}, {'a':5, 'b': 2, 'c':6, 'e':7}, {'a':1, 'b': 3, 'c':8}]
output = {}
for d in ls:
for k, v in d.items():
output[k] = max(output.get(k, float('-inf')), v)
print(output)
Output:
{'a': 5, 'b': 4, 'c': 8, 'e': 7}
Maybe not the cleanest code, but it works:
ls = [{'a':2, 'b':4, 'c':7}, {'a':5, 'b': 2, 'c':6}, {'a':1, 'b': 3, 'c':8}]
complete_dict = {}
for d in ls:
complete_dict.update(d)
unique_keys = {key for key in complete_dict.keys()}
max_dict = {key: max(ls, key=lambda x: x.get(key, 0)).get(key) for key in unique_keys}
print(max_dict)
Assuming the first dictionary contains all the keys, use:
print({k:max(x[k] for x in ls) for k in ls[0].keys()})

Sum Values in List of Dictionaries with some elements as list

I have this list of dictionaries:
list_of_dicts = [{'A':1,'B':2,'C':3,'D':4,'E':5}, {'A':1,'B':1,'C':1,'D':1,'E':1}, {'A':2,'B':2,'C':2,'D':2,'E':2}]
To sum up values, I can use counter like this:
from collections import Counter
import functools, operator
# sum the values with same keys
counter = Counter()
for d in list_of_dicts:
counter.update(d)
result = dict(counter)
result
{'A': 4, 'B': 5, 'C': 6, 'D': 7, 'E': 8}
But how to achieve summation if some key in the dictionary has value as list:
list_of_dicts = [{'A':1,'B':2,'C':3,'D':4,'E':[1,2,3]}, {'A':1,'B':1,'C':1,'D':1,'E':[1,2,3]}, {'A':2,'B':2,'C':2,'D':2,'E':[1,2,3]}]
I want to get this result:
{'A': 4, 'B': 5, 'C': 6, 'D': 7, 'E':[3,6,9]}
If you can not use numpy you can try this:
(using collections.defaultdict)
from collections import defaultdict
list_of_dicts = [{'A':1,'B':2,'C':3,'D':4,'E':[1,2,3]},
{'A':1,'B':1,'C':1,'D':1,'E':[1,2,3]},
{'A':2,'B':2,'C':2,'D':2,'E':[1,2,3]}]
dct = defaultdict(list)
for l in list_of_dicts:
for k,v in l.items():
dct[k].append(v)
for k,v in dct.items():
if isinstance(v[0],list):
dct[k] = [sum(x) for x in zip(*v)]
else:
dct[k] = sum(v)
Output:
>>> dct
defaultdict(list, {'A': 4, 'B': 5, 'C': 6, 'D': 7, 'E': [3, 6, 9]})
If you can use numpy you can try this:
import numpy as np
dct = defaultdict(list)
for l in list_of_dicts:
for k,v in l.items():
dct[k].append(v)
for k,v in dct.items():
dct[k] = (np.array(v).sum(axis=0))
Output:
>>> dct
defaultdict(list, {'A': 4, 'B': 5, 'C': 6, 'D': 7, 'E': array([3, 6, 9])})

Read Multiple Dictionaries into a nested list

I am reading below list into a Counter and I want to group all keys into a nested list as shown below
import collections
A=["cool","lock","cook"]
B=[]
d={}
for i in A:
B.append(collections.Counter(i))
print(B)
## B value is [Counter({'o': 2, 'c': 1, 'l': 1}), Counter({'l': 1, 'o': 1, 'c': 1, 'k': 1}), Counter({'o': 2, 'c': 1, 'k': 1})]
for i in B:
for j in i.keys():
d.setdefault( d[j],[]).append(i.values())
print(d)
I am getting a Key Error, I have used Setdefault() but able to get it work.
Needed output:
{'o':[2,1,2],'c':[1,1,1],'l':[1,1],'k':[1,1] }
Here is how:
import collections
A = ["cool", "lock", "cook"]
B = []
d = {}
for i in A:
B.append(collections.Counter(i))
for i in B:
for j in i:
if j in d:
d[j].append(i[j])
else:
d[j] = [i[j]]
print(d)
Output:
{'c': [1, 1, 1], 'o': [2, 1, 2], 'l': [1, 1], 'k': [1, 1]}
You may even use map when defining B to improve the efficiency:
import collections
A = ["cool", "lock", "cook"]
B = map(collections.Counter, A)
d = {}
for i in B:
for j in i:
if j in d:
d[j].append(i[j])
else:
d[j] = [i[j]]
print(d)

How do I count each unique value for each key in a dictionary containing lists?

I have the following dictionary:
dict = {'A': [1,1,2], 'B': [1,1,1], 'C': [2,2,2,1,2]}
I want the output to tell me how many of each values I have for each key, e.g.:
if value == 1 -> A, 2; B,3; C,1
if value == 2 -> A, 1; B,0; C,4
So far I have:
for i in dict[i]:
if i == 1:
participants_luck += 1
elif i == 2:
participants_skill += 1
This is a flexible solution to count the occurrences of each different value in the dictionary
dict = {"A": [1,1,2], "B": [1,1,1], "C": [2,2,2,1,2]}
different_values = set()
for values in dict.values():
for el in values:
different_values.add(el)
for possible_value in different_values:
print(possible_value)
for key, values in dict.items():
print(key, sum(value == possible_value for value in values))
print("\n")
Output:
1
A 2
B 3
C 1
2
A 1
B 0
C 4
UPDATE: If you want to handle also non list items in dict you can do like this:
from collections.abc import Iterable
dict = {"A": [1,1,2], "B": [1,1,1], "C": [2,2,2,1,2], "D": 1}
different_values = set()
for values in dict.values():
if isinstance(values, Iterable):
for el in values:
different_values.add(el)
else:
different_values.add(values)
for possible_value in different_values:
print(possible_value)
for key, values in dict.items():
if isinstance(values, Iterable):
print(key, sum(value == possible_value for value in values))
else:
print(key, int(values == possible_value))
print("\n")
And the output will be:
1
A 2
B 3
C 1
D 1
2
A 1
B 0
C 4
D 0
Define a function so you can search for different values if you ever need to. Use the count method to make things very easy for yourself.
d = {'A': [1,1,2], 'B': [1,1,1], 'C': [2,2,2,1,2]}
def foo(value, dictionary):
for key,l in dictionary.items():
print(f"{key} : {l.count(value)}")
foo(1,d)
foo(2,d)
This is a one-liner! You can write a dictionary comprehension. We have a dictionary mydict and a value to count. We first iterate over the items in the dictionary. For each list in the dictionary, we iterate over that list, and find the sum of i == value. Because True counts as 1 and False counts as 0, sum(i == value for i in lst) will give the number of i in the lst which are equal to value. Alternatively, you could do lst.count(value). The sum(...) technique is useful when you want to count a condition other than ==, for example if you wanted to count how many elements are less than the given value.
def count(mydict, value):
return {k: sum(i == value for i in lst) for k, lst in mydict.items()}
# Or,
# return {k: lst.count(value) for k, lst in mydict.items()}
d = {'A': [1,1,2], 'B': [1,1,1], 'C': [2,2,2,1,2]}
count(d, 1) # out: {'A': 2, 'B': 3, 'C': 1}
count(d, 2) # out: {'A': 1, 'B': 0, 'C': 4}
You can then access the counts like so:
result = count(d, 1)
print(f"A: {result['A']}, B: {result['B']}, C: {result['C']}")
Or, if you don't want to hardcode the keys of result:
result = count(d, 1)
for k, v in result.items():
print(f"{k}: {v}")
You could use a Counter:
from collections import Counter
cnts={k: Counter(v) for k,v in di.items()}
# {'A': Counter({1: 2, 2: 1}), 'B': Counter({1: 3}), 'C': Counter({2: 4, 1: 1})}
Then just use a comprehension to get the sub counts as needed:
>>> {k:v[1] for k,v in cnts.items()}
{'A': 2, 'B': 3, 'C': 1}
>>> ({k:v[2] for k,v in cnts.items()}
{'A': 1, 'B': 0, 'C': 4}
Would be interesting making a function to do it.
def count_stuff(any_dict, wanted_val):
counted_dict = {}
for key in any_dict.keys():
count = 0
for element in any_dict[key]:
count += (element == wanted_val)
counted_dict[key] = count
return counted_dict
Running your example...
your_dict = {"A": [1,1,2], "B": [1,1,1], "C": [2,2,2,1,2]}
for i in [1, 2]:
print(i, count_stuff(your_dict, i))
Prints
1 {'A': 2, 'B': 3, 'C': 1}
2 {'A': 1, 'B': 0, 'C': 4}

Iterating Over a Dictionary

I am trying to return all the values in a dictionary that have a value greater than the int argurment.
def big_keys(dict, int):
count = []
for u in dict:
if u > int:
count.append(u)
return count
I don't understand why this isn't working. It returns every value in the list rather than just those which are greater than in.
By default, any dict will iterate over its keys, not its values:
>>> d = {'a': 1, 'b': 2}
>>> for i in d:
... print i
...
a
b
To iterate over values, use .values():
>>> for i in d.values():
... print i
...
1
2
With that in mind, your method can be simplified:
def big_keys(d, i):
return [x for x in d.values() if x > i]
I have changed your variable names, since dict and int are both built-ins.
Your method is actually recreating default functionality available in Python. The filter method does what you are trying to do:
>>> d = {'a': 1, 'b': 6, 'd': 7, 'e': 0}
>>> filter(lambda x: x > 5, d.values())
[6, 7]
From your comment it seems you are looking for the keys and not the values. Here is how you would do that:
>>> d = {'a': 21, 'c': 4, 'b': 5, 'e': 30, 'd': 6, 'g': 4, 'f': 2, 'h': 20}
>>> result = []
>>> for k,v in d.iteritems():
... if v > 20:
... result.append(k)
...
>>> result
['a', 'e']
Or, the shorter way:
>>> [k for k,v in d.iteritems() if v > 20]
['a', 'e']
iterating dictionary yields keys for the dictionary.
>>> d = {'key1': 'value1', 'key2': 'value2'}
>>> for x in d:
... print(x)
...
key2
key1
To get values, use dict.values():
>>> for x in d.values():
... print(x)
...
value2
value1
So, you program should read as follow:
def big_keys(dict, int):
count = []
for u in dict.values():
if u > int:
count.append(u)
return count

Categories

Resources