Let's say I have a dictionary:
data = {'a':1, 'b':2, 'c': 3, 'd': 3}
I want to get the maximum value(s) in the dictionary. So far, I have been just doing:
max(zip(data.values(), data.keys()))[1]
but I'm aware that I could be missing another max value. What would be the most efficient way to approach this?
Based on your example, it seems like you're looking for the key(s) which map to the maximum value. You could use a list comprehension:
[k for k, v in data.items() if v == max(data.values())]
# ['c', 'd']
If you have a large dictionary, break this into two lines to avoid calculating max for as many items as you have:
mx = max(data.values())
[k for k, v in data.items() if v == mx]
In Python 2.x you will need .iteritems().
You could try collecting reverse value -> key pairs in a defaultdict, then output the values with the highest key:
from collections import defaultdict
def get_max_value(data):
d = defaultdict(list)
for key, value in data.items():
d[value].append(key)
return max(d.items())[1]
Which Outputs:
>>> get_max_value({'a':1, 'b':2, 'c': 3, 'd': 3})
['c', 'd']
>>> get_max_value({'a': 10, 'b': 10, 'c': 4, 'd': 5})
['a', 'b']
First of all, find what is the max value that occurs in the dictionary. If you are trying to create a list of all the max value(s), then try something like this:
data = {'a':1, 'b':2, 'c': 3, 'd': 3}
max_value = data.get(max(data))
list_num_max_value = []
for letter in data:
if data.get(letter) == max_value:
list_num_max_value.append(max_value)
print (list_num_max_value)
Please let me know if that's not what you are trying to do and I will guide you through the right process.
Related
For example, in dict1 the keys 1, 2, 3 all have the same value 'a', but the keys 3 and 5 have different values, 'b' and 'd'. What I want is:
If N keys have the same value and N >=3, then I want to remove all other elements from the dict and only keep those N key values, which means 'b' & 'd' have to be removed from the dict.
The following code works, but it seems very verbose. Is there a better way to do this?
from collections import defaultdict
dict1 = {1:'a', 2:'a', '3':'b', '4': 'a', '5':'d'}
l1 = [1, 2, 3, 4, 5]
dict2 = defaultdict(list)
for k, v in dict1.items():
dict2[v].append(k)
to_be_removed = []
is_to_be_removed = False
for k, values in dict2.items():
majority = len(values)
if majority>=3:
is_to_be_removed = True
else:
to_be_removed.extend(values)
if is_to_be_removed:
for d in to_be_removed:
del dict1[d]
print(f'New dict: {dict1}')
You can use collections.Counter to get the frequency of every value, then use a dictionary comprehension to retain only the keys that have the desired corresponding value:
from collections import Counter
dict1 = {1:'a', 2:'a', '3':'b', '4': 'a', '5':'d'}
ctr = Counter(dict1.values())
result = {key: value for key, value in dict1.items() if ctr[value] >= 3}
print(result)
This outputs:
{1: 'a', 2: 'a', '4': 'a'}
try to find the max value in a nested dictionary, but showed unhashable type: 'dict_keys'error
Suppose I have this dictionary:
d = {'A': {'a':2, 'b':2, 'c':0},
'B': {'a':2, 'b':0, 'c':1}}
I want the code to return all the key(s) that contain maximum values within the dictionary (i.e. the maximum value in dictionary A is 2, and I want the code to return me the corresponding keys: 'a' and 'b')
['a','b']
here is the code I wrote:
max_value = max(d[Capital_Alph].values()))
return [key for key, value in d[Capital_Alph].items()
if value == max_value]
So you have a dictionary with a str as value and a dict as key, You can do something like this:
d = {'A': {'a':2, 'b':2, 'c':0},
'B': {'a':2, 'b':0, 'c':1}}
print(list(d['A'].keys()))
Returns:
['a', 'b', 'c']
[Finished in 0.8s]
Is this a viable solution to what you are trying to accomplish?
You can not use non-hashable datatypes as keys for sets or dict. You can accomplish your task by:
d = {'A': {'a':2, 'b':2, 'c':0},
'B': {'a':2, 'b':0, 'c':1}}
max_v = {k:max(d[k].values()) for k in d } # get the max value of the inner dict
print(max_v)
for inner in max_v:
print("Max keys of dict {} are: {}".format(inner,
[k for k,v in d[inner].items() if v == max_v[inner]]))
Output:
{'A': 2, 'B': 2} # max values of inner dicts
Max keys of dict A are: ['a', 'b']
Max keys of dict B are: ['a']
The part [k for k,v in d[inner].items() if v == max_v[inner]])) is needed to get all inner keys (if multiple exists) that have the same maximum value.
There are two errors in your code: there are too many ) characters in your calculation of max_value and you can't use return outside a function.
But if I fix those issues and do this:
>>> d = {'A': {'a':2, 'b':2, 'c':0},
'B': {'a':2, 'b':0, 'c':1}}
>>> Capital_Alph = "A"
>>> max_value = max(d[Capital_Alph].values())
>>> [key for key, value in d[Capital_Alph].items()
if value == max_value]
['a', 'b']
it's clear that there isn't a lot else wrong here. To avoid complicating things I didn't put the obvious loop around this:
for Capital_Alph in d:
but you can manage that on your own. Your error message is because you tried to make Capital_Alph a dict_keys object, in other words d.keys(), and use that as a key. You can't do that. You have to step through the list of dictionary keys yourself.
I know this is a frequently asked question, however I do not have access to the Counter module as I'm using v2.6 of Python. I want to count the number of time a specific key appears in a list of dictionaries.
If my dictionary looks like this:
data = [{'a':1, 'b':1}, {'a':1, 'c':1}, {'b':1, 'c':1}, {'a':1, 'c':1}, {'a':1, 'd':1}]
How would I find out how many times "a" appears? I've tried using len, but that only returns the number of values for one key.
len(data['a'])
You can use list comprehension.
data = [{'a':1, 'b':1}, {'a':1, 'c':1}, {'b':1, 'c':1}, {'a':1, 'c':1}, {'a':1, 'd':1}]
sum([1 for d in data if 'a' in d])
Explanation:
First take the dictionary object from list data, check if key 'a' is present in the dictionary or not, if present, add 1 to the list. Then sum the new list.
You won't have access to collections.Counter, but collections.defaultdict was added in Python 2.5
keys and flatten list
data = [j for i in data for j in i.keys()]
# ['a', 'b', 'a', 'c', 'c', 'b', 'a', 'c', 'a', 'd']
collections.defaultdict
from collections import defaultdict
dct = defaultdict(int)
for key in data:
dct[key] += 1
# defaultdict(<type 'int'>, {'a': 4, 'c': 3, 'b': 2, 'd': 1})
If you only need the count for a, there are simpler ways to do this, but this will give you the counts of all keys in your list of dictionaries.
A one-line solution could be:
len([k for d in data for k in d.keys() if k == 'a'])
For this you could write the following function that would work for data in the structure you provided (a list of dicts):
def count_key(key,dict_list):
keys_list = []
for item in dict_list:
keys_list += item.keys()
return keys_list.count(key)
Then, you could invoke the function as follows:
data = [{'a':1, 'b':1}, {'a':1, 'c':1}, {'b':1, 'c':1}, {'a':1, 'c':1}, {'a':1, 'd':1}]
count_a = count_key('a',data)
In this case, count_a will be 4.
This question looks very much like a class assignment. Here is a simple bit of code that will do the job:
n=0
for d in data:
if 'a' in d:
n+=1
print(n)
Here n is a counter, the for loop iterates through the list of dictionaries.
The 'a' in d expression will return true if the key 'a' is in the dictionary d, in which case the counter n will be incremented. At the end the result is printed. I believe in Python 2.6 the brackets would be optional (I am using 3.6).
I have a Dictionary here:
dic = {'A':1, 'B':6, 'C':42, 'D':1, 'E':12}
and a list here:
lis = ['C', 'D', 'C', 'C', 'F']
What I'm trying to do is (also a requirement of the homework) to check whether the values in the lis matches the key in dic, if so then it increment by 1 (for example there's 3 'C's in the lis then in the output of dic 'C' should be 45). If not, then we create a new item in the dic and set the value to 1.
So the example output should be look like this:
dic = {'A':1, 'B':6, 'C':45, 'D':2, 'E':12, 'F':1}
Here's what my code is:
def addToInventory(dic, lis):
for k,v in dic.items():
for i in lis:
if i == k:
dic[k] += 1
else:
dic[i] = 1
return dic
and execute by this code:
dic = addToInventory(dic,lis)
It compiles without error but the output is strange, it added the missing F into the dic but didn't update the values correctly.
dic = {'A':1, 'B':6, 'C':1, 'D':1, 'E':12, 'F':1}
What am I missing here?
There's no need to iterate over a dictionary when it supports random lookup. You can use if x in dict to do this. Furthermore, you'd need your return statement outside the loop.
Try, instead:
def addToInventory(dic, lis):
for i in lis:
if i in dic:
dic[i] += 1
else:
dic[i] = 1
return dic
out = addToInventory(dic, lis)
print(out)
{'A': 1, 'B': 6, 'C': 45, 'D': 2, 'E': 12, 'F': 1}
As Harvey suggested, you can shorten the function a little by making use of dict.get.
def addToInventory(dic, lis):
for i in lis:
dic[i] = dic.get(i, 0) + 1
return dic
The dic.get function takes two parameters - the key, and a default value to be passed if the value associated with that key does not already exist.
If your professor allows the use of libraries, you can use the collections.Counter data structure, it's meant precisely for keeping counts.
from collections import Counter
c = Counter(dic)
for i in lis:
c[i] += 1
print(dict(c))
{'A': 1, 'B': 6, 'C': 45, 'D': 2, 'E': 12, 'F': 1}
I want to make a IF statement inside a for loop, that I want it to be triggered if the variable is equal to any value in the list.
Sample data:
list = [variable1, variable2, variable3]
Right now I have this sample code:
for k, v in result_dict.items():
if k == 'varible1' or k == 'variable2' or k == 'variable2':
But the problem is the list will grow larger and I don't to have to create multiple OR statements for every variable.
how can I do it?
This is what the in operator is for. Do:
list = [variable1, variable2, variable3]
for k, v in result_dict.items():
if k in list:
Another way to do it is with sets:
>>> l = ['a', 'b', 'c']
>>> d = {'a': 1, 'b': 2, 'c': 'three', 'd': 4, 'e': 5, 'f': 6}
>>> keys = set(l).intersection(d.keys())
>>> keys
set(['a', 'c', 'b'])
Then you can iterate over those keys:
for k in set(l).intersection(d.keys()):
do_something(d[k])
This should be more efficient than repetitively calling in on the list. Call set() on the shortest of the list or dictionary.
You may need another FOR loop.
for k, v in result_dict.items():
for i in list:
if i==k: