Python dictionary replace values - python

I have a dictionary with 20 000 plus entries with at the moment simply the unique word and the number of times the word was used in the source text (Dante's Divine Comedy in Italian).
I would like to work through all entries replacing the value with an actual definition as I find them. Is there a simple way to iterate through the keywords that have as a value a number in order to replace (as I research the meaning)?
The dictionary starts:
{'corse': 378, 'cielo,': 209, 'mute;': 16, 'torre,': 11, 'corsa': 53, 'assessin': 21, 'corso': 417, 'Tolomea': 21} # etc.
Sort of an application that will suggest a keyword to research and define.

via dict.update() function
In case you need a declarative solution, you can use dict.update() to change values in a dict.
Either like this:
my_dict.update({'key1': 'value1', 'key2': 'value2'})
or like this:
my_dict.update(key1='value1', key2='value2')
via dictionary unpacking
Since Python 3.5 you can also use dictionary unpacking for this:
my_dict = { **my_dict, 'key1': 'value1', 'key2': 'value2'}
Note: This creates a new dictionary.
via merge operator or update operator
Since Python 3.9 you can also use the merge operator on dictionaries:
my_dict = my_dict | {'key1': 'value1', 'key2': 'value2'}
Note: This creates a new dictionary.
Or you can use the update operator:
my_dict |= {'key1': 'value1', 'key2': 'value2'}

You cannot select on specific values (or types of values). You'd either make a reverse index (map numbers back to (lists of) keys) or you have to loop through all values every time.
If you are processing numbers in arbitrary order anyway, you may as well loop through all items:
for key, value in inputdict.items():
# do something with value
inputdict[key] = newvalue
otherwise I'd go with the reverse index:
from collections import defaultdict
reverse = defaultdict(list)
for key, value in inputdict.items():
reverse[value].append(key)
Now you can look up keys by value:
for key in reverse[value]:
inputdict[key] = newvalue

If you iterate over a dictionary you get the keys, so assuming your dictionary is in a variable called data and you have some function find_definition() which gets the definition, you can do something like the following:
for word in data:
data[word] = find_definition(word)

I think this may help you solve your issue.
Imagine you have a dictionary like this:
dic0 = {0:"CL1", 1:"CL2", 2:"CL3"}
And you want to change values by this one:
dic0to1 = {"CL1":"Unknown1", "CL2":"Unknown2", "CL3":"Unknown3"}
You can use code bellow to change values of dic0 properly respected to dic0to1 without worrying yourself about indexes in dictionary:
for x, y in dic0.items():
dic0[x] = dic0to1[y]
Now you have:
>>> dic0
{0: 'Unknown1', 1: 'Unknown2', 2: 'Unknown3'}

Just had to do something similar. My approach for sanitizing data for python based on Sadra Sabouri's answer:
def sanitize(value):
if str(value) == 'false':
return False
elif str(value) == 'true':
return True
elif str(value) == 'null':
return None
return value
for k,v in some_dict.items():
some_dict[k] = sanitize(v)

data = {key1: value1, key2: value2, key3: value3}
for key in data:
if key == key1:
data[key1] = change
print(data)
this will replace key1: value1 to key1: change

Related

Python update a key in dict if it doesn't exist

I want to insert a key-value pair into dict if key not in dict.keys().
Basically I could do it with:
if key not in d.keys():
d[key] = value
But is there a better way? Or what's the pythonic solution to this problem?
You do not need to call d.keys(), so
if key not in d:
d[key] = value
is enough. There is no clearer, more readable method.
You could update again with dict.get(), which would return an existing value if the key is already present:
d[key] = d.get(key, value)
but I strongly recommend against this; this is code golfing, hindering maintenance and readability.
Use dict.setdefault():
>>> d = {'key1': 'one'}
>>> d.setdefault('key1', 'some-unused-value')
'one'
>>> d # d has not changed because the key already existed
{'key1': 'one'}
>>> d.setdefault('key2', 'two')
'two'
>>> d
{'key1': 'one', 'key2': 'two'}
Since Python 3.9 you can use the merge operator | to merge two dictionaries. The dict on the right takes precedence:
new_dict = old_dict | { key: val }
For example:
new_dict = { 'a': 1, 'b': 2 } | { 'b': 42 }
print(new_dict) # {'a': 1, 'b': 42}
Note: this creates a new dictionary with the updated values.
With the following you can insert multiple values and also have default values but you're creating a new dictionary.
d = {**{ key: value }, **default_values}
I've tested it with the most voted answer and on average this is faster as it can be seen in the following example, .
Speed test comparing a for loop based method with a dict comprehension with unpack operator method.
if no copy (d = default_vals.copy()) is made on the first case then the most voted answer would be faster once we reach orders of magnitude of 10**5 and greater. Memory footprint of both methods are the same.
You can also use this solution in only one line of code:
dict[dict_key] = dict.get(dict_key,value)
The second argument of dict.get is the value you want to assign to the key in case the key does not exist. Since this evaluates before the assignment to dict[dict_key] = , we can be sure that they key will exist when we try to access it.

Merging values from 2 dictionaries (Python)

(I'm new to Python!)
Trying to figure out this homework question:
The function will takes a​s input​ two dictionaries, each mapping strings to integers. The function will r​eturn​ a dictionary that maps strings from the two input dictionaries to the sum of the integers in the two input dictionaries.
my idea was this:
def ​add(​dicA,dicB):
dicA = {}
dicB = {}
newdictionary = dicA.update(dicB)
however, that brings back None.
In the professor's example:
print(add({'alice':10, 'Bob':3, 'Carlie':1}, {'alice':5, 'Bob':100, 'Carlie':1}))
the output is:
{'alice':15, 'Bob':103, 'Carlie':2}
My issue really is that I don't understand how to add up the values from each dictionaries. I know that the '+' is not supported with dictionaries. I'm not looking for anyone to do my homework for me, but any suggestions would be very much appreciated!
From the documentation:
update([other])
Update the dictionary with the key/value pairs from other, overwriting existing keys. Return None.
You don't want to replace key/value pairs, you want to add the values for similar keys. Go through each dictionary and add each value to the relevant key:
def ​add(​dicA,dicB):
result = {}
for d in dicA, dicB:
for key in d:
result[key] = result.get(key, 0) + d[key]
return result
result.get(key, 0) will retrieve the value of an existing key or produce 0 if key is not yet present.
First of all, a.update(b) updates a in place, and returns None.
Secondly, a.update(b) wouldn't help you to sum the keys; it would just produce a dictionary with the resulting dictionary having all the key, value pairs from b:
>>> a = {'alice':10, 'Bob':3, 'Carlie':1}
>>> b = {'alice':5, 'Bob':100, 'Carlie':1}
>>> a.update(b)
>>> a
{'alice': 5, 'Carlie': 1, 'Bob': 100}
It'd be easiest to use collections.Counter to achieve the desired result. As a plus, it does support addition with +:
from collections import Counter
def add(dicA, dicB):
return dict(Counter(dicA) + Counter(dicB))
This produces the intended result:
>>> print(add({'alice':10, 'Bob':3, 'Carlie':1}, {'alice':5, 'Bob':100, 'Carlie':1}))
{'alice': 15, 'Carlie': 2, 'Bob': 103}
The following is not meant to be the most elegant solution, but to get a feeling on how to deal with dicts.
dictA = {'Alice':10, 'Bob':3, 'Carlie':1}
dictB = {'Alice':5, 'Bob':100, 'Carlie':1}
# how to iterate through a dictionary
for k,v in dictA.iteritems():
print k,v
# make a new dict to keep tally
newdict={}
for d in [dictA,dictB]: # go through a list that has your dictionaries
print d
for k,v in d.iteritems(): # go through each dictionary item
if not k in newdict.keys():
newdict[k]=v
else:
newdict[k]+=v
print newdict
Output:
Bob 3
Alice 10
Carlie 1
{'Bob': 3, 'Alice': 10, 'Carlie': 1}
{'Bob': 100, 'Alice': 5, 'Carlie': 1}
{'Bob': 103, 'Alice': 15, 'Carlie': 2}
def ​add(​dicA,dicB):
You define a function that takes two arguments, dicA and dicB.
dicA = {}
dicB = {}
Then you assign an empty dictionary to both those variables, overwriting the dictionaries you passed to the function.
newdictionary = dicA.update(dicB)
Then you update dicA with the values from dicB, and assign the result to newdictionary. dict.update always returns None though.
And finally, you don’t return anything from the function, so it does not give you any results.
In order to combine those dictionaries, you actually need to use the values that were passed to it. Since dict.update mutates the dictionary it is called on, this would change one of those passed dictionaries, which we generally do not want to do. So instead, we use an empty dictionary, and then copy the values from both dictionaries into it:
def add (dicA, dicB):
newDictionary = {}
newDictionary.update(dicA)
newDictionary.update(dicB)
return newDictionary
If you want the values to sum up automatically, then use a Counter instead of a normal dictionary:
from collections import Counter
def add (dicA, dicB):
newDictionary = Counter()
newDictionary.update(dicA)
newDictionary.update(dicB)
return newDictionary
I suspect your professor wants to achieve this using more simple methods. But you can achieve this very easily using collections.Counter.
from collections import Counter
def add(a, b):
return dict(Counter(a) + Counter(b))
Your professor probably wants something like this:
def add(a, b):
new_dict = copy of a
for each key/value pair in b
if key in new_dict
add value to value already present in new_dict
else
insert key/value pair into new_dict
return new_dict
You can try this:
def add(dict1, dict2):
return dict([(key,dict1[key]+dict2[key]) for key in dict1.keys()])
I personally like using a dictionary's get method for this kind of merge:
def add(a, b):
result = {}
for dictionary in (a, b):
for key, value in dictionary.items():
result[key] = result.get(key, 0) + value
return result

Dividing dictionary into nested dictionaries, based on the key's name on Python 3.4

I have the following dictionary (short version, real data is much larger):
dict = {'C-STD-B&M-SUM:-1': 0, 'C-STD-B&M-SUM:-10': 4.520475, 'H-NSW-BAC-ART:-9': 0.33784000000000003, 'H-NSW-BAC-ART:0': 0, 'H-NSW-BAC-ENG:-59': 0.020309999999999998, 'H-NSW-BAC-ENG:-6': 0,}
I want to divide it into smaller nested dictionaries, depending on a part of the key name.
Expected output would be:
# fixed closing brackets
dict1 = {'C-STD-B&M-SUM: {'-1': 0, '-10': 4.520475}}
dict2 = {'H-NSW-BAC-ART: {'-9': 0.33784000000000003, '0': 0}}
dict3 = {'H-NSW-BAC-ENG: {'-59': 0.020309999999999998, '-6': 0}}
Logic behind is:
dict1: if the part of the key name is 'C-STD-B&M-SUM', add to dict1.
dict2: if the part of the key name is 'H-NSW-BAC-ART', add to dict2.
dict3: if the part of the key name is 'H-NSW-BAC-ENG', add to dict3.
Partial code so far:
def divide_dictionaries(dict):
c_std_bem_sum = {}
for k, v in dict.items():
if k[0:13] == 'C-STD-B&M-SUM':
c_std_bem_sum = k[14:17], v
What I'm trying to do is to create the nested dictionaries that I need and then I'll create the dictionary and add the nested one to it, but I'm not sure if it's a good way to do it.
When I run the code above, the variable c_std_bem_sum becomes a tuple, with only two values that are changed at each iteration. How can I make it be a dictionary, so I can later create another dictionary, and use this one as the value for one of the keys?
One way to approach it would be to do something like
d = {'C-STD-B&M-SUM:-1': 0, 'C-STD-B&M-SUM:-10': 4.520475, 'H-NSW-BAC-ART:-9': 0.33784000000000003, 'H-NSW-BAC-ART:0': 0, 'H-NSW-BAC-ENG:-59': 0.020309999999999998, 'H-NSW-BAC-ENG:-6': 0,}
def divide_dictionaries(somedict):
out = {}
for k,v in somedict.items():
head, tail = k.split(":")
subdict = out.setdefault(head, {})
subdict[tail] = v
return out
which gives
>>> dnew = divide_dictionaries(d)
>>> import pprint
>>> pprint.pprint(dnew)
{'C-STD-B&M-SUM': {'-1': 0, '-10': 4.520475},
'H-NSW-BAC-ART': {'-9': 0.33784000000000003, '0': 0},
'H-NSW-BAC-ENG': {'-59': 0.020309999999999998, '-6': 0}}
A few notes:
(1) We're using nested dictionaries instead of creating separate named dictionaries, which aren't convenient.
(2) We used setdefault, which is a handy way to say "give me the value in the dictionary, but if there isn't one, add this to the dictionary and return it instead.". Saves an if.
(3) We can use .split(":") instead of hardcoding the width, which isn't very robust -- at least assuming that's the delimiter, anyway!
(4) It's a bad idea to use dict, the name of a builtin type, as a variable name.
That's because you're setting your dictionary and overriding it with a tuple:
>>> a = 1, 2
>>> print a
>>> (1,2)
Now for your example:
>>> def divide_dictionaries(dict):
>>> c_std_bem_sum = {}
>>> for k, v in dict.items():
>>> if k[0:13] == 'C-STD-B&M-SUM':
>>> new_key = k[14:17] # sure you don't want [14:], open ended?
>>> c_std_bem_sum[new_key] = v
Basically, this grabs the rest of the key (or 3 characters, as you have it, the [14:None] or [14:] would get the rest of the string) and then uses that as the new key for the dict.

Python getting a string (key + value) from Python Dictionary

I have dictionary structure. For example:
dict = {key1 : value1 ,key2 : value2}
What I want is the string which combines the key and the value
Needed string -->> key1_value1 , key2_value2
Any Pythonic way to get this will help.
Thanks
def checkCommonNodes( id , rs):
for r in rs:
for key , value in r.iteritems():
kv = key+"_"+value
if kv == id:
print "".join('{}_{}'.format(k,v) for k,v in r.iteritems())
A list of key-value strs,
>>> d = {'key1': 'value1', 'key2': 'value2'}
>>> ['{}_{}'.format(k,v) for k,v in d.iteritems()]
['key2_value2', 'key1_value1']
Or if you want a single string of all key-value pairs,
>>> ', '.join(['{}_{}'.format(k,v) for k,v in d.iteritems()])
'key2_value2, key1_value1'
EDIT:
Maybe you are looking for something like this,
def checkCommonNodes(id, rs):
id_key, id_value = id.split('_')
for r in rs:
try:
if r[id_key] == id_value:
print "".join('{}_{}'.format(k,v) for k,v in r.iteritems())
except KeyError:
continue
You may also be wanting to break after printing - hard to know exactly what this is for.
Assuming Python 2.x, I would use something like this
dict = {'key1': 'value1', 'key2': 'value2'}
str = ''.join(['%s_%s' % (k,v) for k,v in dict.iteritems()])
def checkCommonNodes(id, rs):
k,v = id.split('_')
for d in rs:
if d.get(k) == v:
return id
retun None
Updated answer for Python 3.x
Example one - join a single key, value in the form "key_value"
k = 'key1'
v = 'value1'
mystring = f'{k}={v}'
print(mystring)
# result -> key1=value1
Example two: create a list of all key-value pairs as strings in the form "key_value"
mydict = {'key1': 'value1', 'key2': 'value2'}
mylist = [f'{k}_{v}' for k,v in mydict.items()]
print(mylist)
# result -> ['key1_value1', 'key2_value2']
Example three: transform a list to a string
result = ', '.join(mylist)
print(result)
# result -> key1_value1, key2_value2
Putting it all together - join all key-value pairs in a dictionary and output as a string.
mydict = {'key1': 'value1', 'key2': 'value2'}
result = ', '.join([f'{k}_{v}' for k,v in mydict.items()])
print(result)
# result -> key1_value1, key2_value2
This is the same basic answer provided by Jared, but now with Python 3.x we use the .items() function instead of .iteritems(), and we can use an f-string instead of the string format() function (although the latter does still work too).
This may not be exactly the perfect answer to the original question asked 12+ years ago (!) but it is a more generic answer about transforming dictionary key-value pairs to (key + value), as indicated by the question title.

index python dictionary by value [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Inverse dictionary lookup - Python
Is there a built in way to index a dictionary by value in Python.
e.g. something like:
dict = {'fruit':'apple','colour':'blue','meat':'beef'}
print key where dict[key] == 'apple'
or:
dict = {'fruit':['apple', 'banana'], 'colour':'blue'}
print key where 'apple' in dict[key]
or do I have to manually loop it?
You could use a list comprehension:
my_dict = {'fruit':'apple','colour':'blue','meat':'beef'}
print [key for key, value in my_dict.items() if value == 'apple']
The code above is doing almost exactly what said you want:
print key where dict[key] == 'apple'
The list comprehension is going through all the key, value pairs given by your dictionary's items method, and making a new list of all the keys where the value is 'apple'.
As Niklas pointed out, this does not work when your values could potentially be lists. You have to be careful about just using in in this case since 'apple' in 'pineapple' == True. So, sticking with a list comprehension approach requires some type checking. So, you could use a helper function like:
def equals_or_in(target, value):
"""Returns True if the target string equals the value string or,
is in the value (if the value is not a string).
"""
if isinstance(target, str):
return target == value
else:
return target in value
Then, the list comprehension below would work:
my_dict = {'fruit':['apple', 'banana'], 'colour':'blue'}
print [key for key, value in my_dict.items() if equals_or_in('apple', value)]
You'll have to manually loop it, but if you'll need the lookup repeatedly this is a handy trick:
d1 = {'fruit':'apple','colour':'blue','meat':'beef'}
d1_rev = dict((v, k) for k, v in d1.items())
You can then use the reverse dictionary like this:
>>> d1_rev['blue']
'colour'
>>> d1_rev['beef']
'meat'
Your requirements are more complex than you realize:
You need to handle both list values and plain values
You don't actually need to get back a key, but a list of keys
You could solve this in two steps:
normalize the dict so that every value is a list (every plain value becomes a single-element)
build a reverse dictionary
The following functions will solve this:
from collections import defaultdict
def normalize(d):
return { k:(v if isinstance(v, list) else [v]) for k,v in d.items() }
def build_reverse_dict(d):
res = defaultdict(list)
for k,values in normalize(d).items():
for x in values:
res[x].append(k)
return dict(res)
To be used like this:
>>> build_reverse_dict({'fruit':'apple','colour':'blue','meat':'beef'})
{'blue': ['colour'], 'apple': ['fruit'], 'beef': ['meat']}
>>> build_reverse_dict({'fruit':['apple', 'banana'], 'colour':'blue'})
{'blue': ['colour'], 'apple': ['fruit'], 'banana': ['fruit']}
>>> build_reverse_dict({'a':'duplicate', 'b':['duplicate']})
{'duplicate': ['a', 'b']}
So you just build up the reverse dictionary once and then lookup by value and get back a list of keys.

Categories

Resources