deleting entries in a dictionary based on a condition - python

I have a dictionary with names as key and (age, Date of Birth) tuple as the value for those keys. E.g.
dict = {'Adam' : (10, '2002-08-13'),
'Eve' : (40, '1972-08-13')}
I want to delete all the keys which have age > 30 for their age in value tuple, how can I do that? I am accessing age of each key using dict[name][0] where dict is my dictionary.

The usual way is to create a new dictionary containing only the items you want to keep:
new_data = {k: v for k, v in data.items() if v[0] <= 30}
If you need to change the original dictionary in place, you can use a for-loop:
for k, v in list(data.items()):
if v[0] > 30:
del data[k]
Note that list(data.items()) creates a shallow copy of the items of the dictionary, i.e. a new list containing references to all keys and values, so it's safe to modify the original dict inside the loop.

Related

Dictionary sized change due to iteration of dict

I am attempting to remove key-value pairs from a dict when a sub-dictionary matches values from another dictionary.
Example set-up:
e = {'a':{'aa':'yes'}, 'b':{'ac':'no'}, 'a':{'aa':'yes'}}
f = {'a':{'aa':'yes'}, 'e':{'ab':'no'}, 'a':{'aa':'yes'}}
for keys, values in e.items():
for k, v in f.items():
if values.get('aa') == v.get('aa'):
e.pop(keys)
RuntimeError: dictionary changed size during iteration
Expected result:
#from
e = {'a':{'aa':'yes'}, 'b':{'ac':'no'}, 'a':{'aa':'yes'}}
#to
e = {'b':{'ac':'no'}}
With single dict comprehension:
e = {k:v for k, v in e.items() if v.items() != f.get(k, {}).items()}
{'b': {'ac': 'no'}}
dict.get(key[, default]) allows you to set the needed(or preferred) default value returned for the key in dict
In general, you should not add or remove items from iterables that you are currently iterating over.
As you've been told, you can't modify the length of a thing while you're iterating it. There are a few options here, such as:
Saving a list of what you want to remove, then doing it later:
to_remove = []
for keys, values in e.items():
for k, v in f.items():
if values.get('aa') == v.get('aa'):
to_remove.append(keys)
for tr in to_remove:
e.pop(tr)
Cloning the object, so that what you're iterating does not change but the original object can be modified. This is even more memory expensive than the previous however.
for keys, values in dict(e).items(): # or list(e.items())
for k, v in f.items():
if values.get('aa') == v.get('aa'):
e.pop(keys)
You could also, in your case, simply create a new object:
g = {}
for keys, values in e.items():
for k, v in f.items():
if values.get('aa') != v.get('aa'):
g[keys] = values

Dictionary comprehensions

Dictionary comprehensions
num_dict={1:1,2:4,3:9}
twice_num_dict={key: (value if value*2 >=8 else None)for (key,value) in num_dict.items()}
print(twice_num_dict)
Dictionary comprehensionsi wanted to create a new dict where only key:value pairs of the existing dict will be there in the new_dict if the value*2 of the first dict was >=8 i used if and else here but idk what to type in else condition so that the key value pair of 1:1 is not printed at all
You should place your if clause after your for clause in the comprehension, like so:
{k: v for k, v in d.items() if v * 2 >= 8}

Python adding the values

# Initialising list of dictionary
ini_dict = [{'a':5, 'b':10, 'c':90},
{'a':45, 'b':78},
{'a':90, 'c':10}]
# printing initial dictionary
print ("initial dictionary", (ini_dict))
# sum the values with same keys
result = {}
for d in ini_dict:
for k in d.keys():
result[k] = result.get(k,0) + d[k]
print("resultant dictionary : ", (result))
Can someone explain the program line by line
Creating a list of dictionary's
ini_dict = [{'a':5, 'b':10, 'c':90},
{'a':45, 'b':78},
{'a':90, 'c':10}]
Prints out the list with dictionary's
print ("initial dictionary", (ini_dict))
Creates a new dictionary
result = {}
Loop's through the List of dictionarys
for d in ini_dict:
so the first d would be {'a':5, 'b':10, 'c':90}
Loop's through the keys of that dict
for k in d.keys():
-> a, b and c
Creates or gets the same key in the result dict and adds the value from the current key. Default value for a new created key is 0.
result[k] = result.get(k,0) + d[k]
Prints out the result dict
print("resultant dictionary : ", (result))
the first line initialises a list of three dictionaries.
ini_dict = [{'a':5, 'b':10, 'c':90},
{'a':45, 'b':78},
{'a':90, 'c':10}]
next up, the dictionary is printed
print ("initial dictionary", (ini_dict))
finally, a weighted histogram is made of the dictionaries based on the keys of the elements within said dictionaries. This is done in three steps:
iterating over the list of dictionaries to get at each different dictionary.
for d in ini_dict:
remember: ini_dict is a list of dictionaries. when you for-loop over a list, the symbol (here d) becomes each of the dictionaries.
iterating over the keys in the dictionary. The method dict.keys() returns a list of keys, over which can be iterated.
for k in d.keys():
finally, for each key in the dictionary the corresponding key in the result dictionary is modified to add the new value. with result.get(k,0) the value for the key k in the result dictionary is fetched, but 0 is the default value if the key is not present.
result[k] = result.get(k,0) + d[k]
This just replaces the result with the previous result + the value in d.
At the end of this bit of code, the result dictionary has the added value of each of the keys.

Delete items in a dictionary with values that don't equal the highest value in Python

Essentially I want to delete every key in a dictionary if its value doesn't equal the highest value.
Let's say this is the dictionary:
myDict = {"Bob": 1, "Bill": 5, "Barry": 4, "Steve": 5}
I'm able to sort it by value using this:
myDict = sorted(myDict, key=myDict.get, reverse=True)
Now I want to remove any key in the dictionary that doesn't equal the highest value (in this case '5'). To end up with this:
myDict = {"Bill": 5, "Steve": 5}
I've tried using this for loop:
for item, v in myDict:
if v < myDict[0]:
del myDict[v]
But I get this error:
ValueError: too many values to unpack (expected 2)
This is a) my first time posting here, and b) I've only been learning Python for a few months so I'm sorry if I've made any stupid mistakes.
for item, v in myDict just give you keys mydict, and you are collecting that key in item, v that's why,
use myDict.items() or myDict.iteritems().
for item, v in myDict.iteritems():
if v < myDict[0]:
del myDict[v]
To get Highest value of myDict
max(myDict.values())
To delete keys from Dict never change the iterator you are iterating on, it will give you RuntimeError. So copy it in another variable and change previous one as Anand S Kumar suggested.
You should never alter the object you're iterating over, that usually yields unexpected results (internal pointers get shifted and you miss elements in your iteration and such). You best gather the keys you want to delete and then remove the keys in a separate iteration:
keys = [k for k in myDict.keys() if myDict[k] == max(myDict.values())];
for k in keys: del myDict[k];
It might be best to put the max expression in a variable too so it doesn't get evaluated multiple times. Not sure if Python's able to optimize that for you (probably not).
You can use dictionary comprehension to create a new dictionary:
newDict = {k: v for k,v in myDict.items() if v == max(myDict.values())}
The output for newDict:
{'Steve': 5, 'Bill': 5}

how to delete a key from a dictionary with the highest value?

I have a simple question (or so I thought).
I have a dictionary, lets say it looks like this:
dict = {'A':100, 'a':10, 'T':50, 't':5}
I simply want to delete the key with the highest value. I tried this:
del max(dict.values())
and this is the error message: 'Syntax Error: canĀ“t delete function call'.
I want the end result to be:
dict = {'a':10, 'T':50, 't':5}
You need to get a hold of the key to the max value.
Try this instead:
del d[max(d, key=d.get)]
Also, you should avoid calling your variable dict because it shadows the built-in name.
max(d.values()) will give you the maximum value (100), but to delete an entry from a dictionary you need the corresponding key ('A').
You can do this:
d = {'A':100, 'a':10, 'T':50, 't':5}
key_to_delete = max(d, key=lambda k: d[k])
del d[key_to_delete]
By the way, you shouldn't name your dictionary dict because that's the name of a built-in type.
If there may be multiple entries with the same maximum value and you want to delete all of them:
val_to_delete = max(d.values())
keys_to_delete = [k for k,v in d.iteritems() if v==val_to_delete]
for k in keys_to_delete:
del d[k]

Categories

Resources