Merge values of dictionary into one if keys match condition - python

I have a dictionary called, say, tempDict which is filled as such:
tempDict = {'a': 100, 'b': 200, 'c': 120, 'b_ext1': 4, 'd': 1021, 'a_ext1': 21, 'f_ext1': 12}
In my setup, I need to loop over the keys and if for any key that has a '_ext1' suffix, I want to rewrite or create a new dictionary keeping an unaltered key (preferably without the 'ext1') but with the values merged.
i.e.:
newDict = {'a': 121, 'b': 204, 'c': 120, 'd': 1021, 'f_ext1':12}
Notice, the last entry in the dictionary should be unchanged as there is no 'f' unsuffixed with '_ext1'
The values themselves won't be integers, however the operation is similar.
Does anyone have any ideas?

newDict = {}
for k in tempDict:
if k.endswith("_ext1") and k[:-5] in tempDict:
newDict[k[:-5]] = newDict.get(k[:-5],0)+tempDict[k]
else:
newDict[k] = newDict.get(k,0)+tempDict[k]

Iterate over the keys (items) in the sorted order and sum or add values. This works because keys like "a", "f" sort before "a_ext1", "f_ext1":
>>> d = {}
>>> for k, v in sorted(tempDict.items()):
... if k[0] in d:
... d[k[0]] += v
... else:
... d[k] = v
...
>>> d
{'a': 121, 'c': 120, 'b': 204, 'd': 1021, 'f_ext1': 12}

Related

Search for key in nested Python dictonary

I want to search for key-value pairs in Python dict. My dict is nested, so simple solution like:
if 'keyname' in my_dict:
...
or:
for key, value in my_dict.items():
if 'keyname' == key:
does not work for me.
This is my dict:
my_dict = {'a': 111,
'b': 222,
'c':{'d': 333,
'e': 444},
'f':555,
'g':{'h': {'i': 666}}}
And I want to find value of 'i' or 'd', whats the simplest way to do that?
I do not care for name of the key that has nested dict. For example, I do not care for key name of 'c' or 'g' or 'h', I only care about key-values (key-number).
Is there a way to transform my dict to look like this:
my_result = {'a': 111,
'b': 222,
'd': 333,
'e': 444,
'f': 555,
'i': 666}
In that way it would be easy.
You can flatten the dictionary using recursion here.
def flat(data):
out = {}
for k, v in data.items():
if isinstance(v, dict):
out.update(flat(v))
else:
out[k] = v
return out
flat(my_dict)
# {'a': 111, 'b': 222, 'd': 333, 'e': 444, 'f': 555, 'i': 666}
try this one:
def find_value(_key, _dict):
for key, value in list(_dict.items()):
if isinstance(value, dict):
result = find_value(_key, value)
if result:
return result
if key == _key:
return value

Python creating nested dictionary from a List with repeating keys

I am trying to convert the list to a dictionary.
I have a list of list like this and some of the first values of mini lists are repeating:
list = [["DDS 500","A",300], ["DDS 500","B",100], ["AGB 850","C",250], ["AGB 850","B",350], ["UNI 100","D",900]]
The first value of mini lists will be key . Then, for each mini list second and third value will be the "value" for that key and the values also should be a dictionary. As a result, Final dictionary should be like this:
dict = { "DDS 500":{"A":300,"B":100}, "AGB 850":{"C":250,"B":350}, "UNI 100":{"D":900} }
You can use collections.defaultdict
from collections import defaultdict
lst= [["DDS 500","A",300], ["DDS 500","B",100], ["AGB 850","C",250], ["AGB 850","B",350], ["UNI 100","D",900]]
out=defaultdict(dict)
for k,ik,iv in lst:
out[k].update({ik:iv})
Output:
defaultdict(dict,
{'DDS 500': {'A': 300, 'B': 100},
'AGB 850': {'C': 250, 'B': 350},
'UNI 100': {'D': 900}})
you can use dict.setdefault if you do not want to import any module:
result = {}
for k1, k2, v in my_list:
result.setdefault(k1, {})[k2] = v
result
output:
{'DDS 500': {'A': 300, 'B': 100},
'AGB 850': {'C': 250, 'B': 350},
'UNI 100': {'D': 900}}
You could do it in two steps: 1) create the dictionary with all keys and and empty dictionary as value, 2) merge the values as dictionaries into each key:
lst = [["DDS 500","A",300], ["DDS 500","B",100], ["AGB 850","C",250], ["AGB 850","B",350], ["UNI 100","D",900]]
d = { k:dict() for k,*_ in lst }
for k,*v in lst: d[k].update(dict([v]))
output:
print(d)
# {'DDS 500': {'A': 300, 'B': 100}, 'AGB 850': {'C': 250, 'B': 350}, 'UNI 100': {'D': 900}}

Python - type conversion loop through dictionary

I have a dictionary filled with number strings and i want to convert every of those values into binary. Here is what i tried:
for k,v in ValueDict.items():
ValueDict.update(k:bin(v))
However this does not work. PyCharm says "Illegal target for variable annotation", i dont understand what this means. As far as i know, variable annotation is a way of "commenting" on the types of a variable, but i dont understand how this is related to my issue...
Thanks in advance!
Try using dictionary comprehension:
print({k:bin(v) for k,v in ValueDict.items()})
Or if version less then 2.5:
print(dict((k:bin(v) for k,v in ValueDict.items())))
Your code doesn't work from : in ValueDict.update(k:bin(v))
To use your style:
for k,v in ValueDict.items():
ValueDict.update({k:bin(v)})
Or:
for k,v in ValueDict.items():
ValueDict[k]=bin(v)
You need to provide a dict to update method.
for k,v in ValueDict.items():
ValueDict.update({k:bin(v)})
See the documentation at dict.update:
Update the dictionary with the key/value pairs from other, overwriting existing keys. Return None.
update() accepts either another dictionary object or an iterable of key/value pairs (as tuples or other iterables of length two). If keyword arguments are specified, the dictionary is then updated with those key/value pairs: d.update(red=1, blue=2).
Examples:
# dict expression
d = {"a":1, "b":2, "c":3}
>>> {'a': 1, 'c': 3, 'b': 2}
# multiple updates: no loop needed
d.update( {"a" : 11, "b" : 22} )
>>> {'a': 11, 'c': 3, 'b': 22}
# multiple adds: no loop needed (also no '' around keys)
d.update( A = 111, B = 22 )
>>> {'a': 11, 'A': 111, 'c': 3, 'b': 22, 'B': 22}
# updating all keys using loop
for k,v in d.items():
d[k]=v*2
>>> {'a': 22, 'A': 222, 'c': 6, 'b': 44, 'B': 44}
# add values to a list if same keys and not yet in
# providing an existing key here would overwrite that one
new_ones = ( ("X",42), ("X",4711) )
for k,v in new_ones:
entry = d.setdefault(k,[])
entry.append(v)
>>> {'a': 22, 'A': 222, 'c': 6, 'b': 44, 'B': 44, 'X': [42, 4711]}
# no loop - update from iterable of key/value pairs
new_ones = ( ("i",42), ("j",4711) )
d.update(new_ones)
>>> {'a': 22, 'A': 222, 'c': 6, 'b': 44, 'i': 42, 'j': 4711, 'B': 44, 'X': [42, 4711]}

Weave two dictionaries into one

I have two dictionaries:
dict1 = {'a': 1,
'b': 2,
'c': 3,
'd': 4,
'x': 5}
and
dict2 = {'a': 'start',
'b': 'start',
'c': 'end',
'd': 'end'}
I am trying to create a new dictionary that maps the values start and end as keys to a dictionary that would contain the info of dict1, while keeping those that are not present in dict2 as keys, e.g.:
dict3 = {'start': {'a': 1, 'b': 2},
'end': {'c': 3, 'd': 4},
'x': {'x': 5}
}
Use dict.setdefault() to create the nested dictionaries in dict3 if not yet there, and dict.get() to determine the key in the top-level output dictionary:
dict3 = {}
for k, v in dict1.items():
nested = dict3.setdefault(dict2.get(k, k), {})
nested[k] = v
So dict2.get(k, k) will produce the value from dict2 for a given key from dict1, using the key itself as a default. So for the 'x' key, that'll produce 'x' as there is no mapping in dict2 for that key.
Demo:
>>> dict3 = {}
>>> for k, v in dict1.items():
... nested = dict3.setdefault(dict2.get(k, k), {})
... nested[k] = v
...
>>> dict3
{'start': {'a': 1, 'b': 2}, 'end': {'c': 3, 'd': 4}, 'x': {'x': 5}}
I actually figured it out while abstracting the example and typing up my question here (should have maybe done this earlier...). Anyways: Yay!
So here is my solution, in case it may help someone. If someone knows a swifter or more elegant way to do it, I would be glad to learn!
dict3 = dict()
for k, v in dict1.items():
# if the key of dict1 exists also in dict2
if k in dict2.keys():
# get its value (the keys-to-be for the new dict3)
new_key = dict2[k]
# if the new key is already in the new dict
if new_key in dict3.keys():
# appends new dict entry to dict3
dict3[new_key].update({k: v})
# otherwise create a new entry
else:
dict3[new_key] = {k: v}
# if there is no corresponding mapping present
else:
# treat the original key as the new key and add to dict3
no_map = k
dict3[no_map] = {k: v}

How to remove dictionary key with known value?

Assume python dict:
mydict = {'a': 100, 'b': 200, 'c': 300}
I know one of the values:
value = 200
How to remove the 'b': 200 pair from the dict? I need this:
mydict = {'a': 100, 'c': 300}
Use a dictionary comprehension. Note that (as jonrsharpe has stated) this will create a new dictionary which excludes the key:value pair that you want to remove. If you want to delete it from your original dictionary then please see his answer.
>>> d = {'a': 100, 'b': 200, 'c': 300}
>>> val = 200
# Use d.items() for Python 2.x and d.iteritems() for Python 3.x
>>> d2 = {k:v for k,v in d.items() if v != val}
>>> d2
{'a': 100, 'c': 300}
It sounds like you want:
for key, val in list(mydict.items()):
if val == value:
del mydict[key]
break # unless you want to remove multiple occurences
You'll need to loop over every items(), either with dict comprehension:
new_dict = {k:v for k,v in my_dict.items() if predicate(value)}
Or modifying the existing dictionary:
for k,v in my_dict.items():
if not predicate(v):
del my_dict[k]
The simplest i found:
for key in [k for k,v in mydict.items() if v==200]:
del mydict[key]

Categories