Working with dictionary of dictionaries in python - python

What I want the code below to achieve is that for which ever dictionary who has smaller value of temporary key, add an item in that dictionary with key "permanent" and value same as the value for the temporary key.
Variable="a"
a_list={'a': {'c': '2', 'b': '1'}, 'c': {'a': '2', 'b': '3'}, 'b': {'a': '1', 'c': '3'}}
a_list[Variable]["permanent"]="1"
for item in a_list[Variable].keys():
try:
if a_list[Variable][item]!=0:
a_list[item]["temporary"]=a_list[Variable][item]
except KeyError:
pass
for item in a_list.keys():
if "permanent" in a_list[item].keys():
del a_list[item]
print a_list
the output now is
{'c': {'a': '2', 'b': '3', 'temporary': '2'}, 'b': {'a': '1', 'c': '3', 'temporary': '1'}}
But after adding an statement I want the output to be
{'c': {'a': '2', 'b': '3', 'temporary': '2'}, 'b': {'a': '1', 'c': '3', 'temporary': '1', 'permanent': '1'}}
I don't know how to achieve this by comparing the two temporary keys in the two dictionaries.
Would very much appreciate any help!

The min function will iterate over a list. If given a special key= named parameter, it will use the one-argument function passed in as the key= function to extract the value to use for comparison purposes.
You show dictionaries using only strings containing digits. The maximum string is therefore 'A' (asciibetically later than a digit). So:
max_value = 'A'
min_temp = min(a_list.keys(), key= lambda k: a_list[k].get('temporary', max_value))
At this point, min_temp has the first key in a_list that has the lowest value for sub-dict key 'temporary', or if none had that subkey, the first key returned by keys() (with a defaulted value of max_value). So let's double-check that it was a valid match:
if 'temporary' in a_list[min_temp]:
a_list[min_temp]['permanent'] = a_list[min_temp]['permanent']

Related

How to merge data from multiple dictionaries with repeating keys?

I have two dictionaries:
dict1 = {'a': '2', 'b': '10'}
dict2 = {'a': '25', 'b': '7'}
I need to save all the values for same key in a new dictionary.
The best i can do so far is: defaultdict(<class 'list'>, {'a': ['2', '25'], 'b': ['10', '7']})
dd = defaultdict(list)
for d in (dict1, dict2):
for key, value in d.items():
dd[key].append(value)
print(dd)
that does not fully resolve the problem since a desirable result is:
a = {'dict1':'2', 'dict2':'25'}
b = {'dict2':'10', 'dict2':'7'}
Also i possibly would like to use new dictionary key same as initial dictionary name
Your main problem is that you're trying to cross the implementation boundary between a string value and a variable name. This is almost always bad design. Instead, start with all of your labels as string data:
table = {
"dict1": {'a': '2', 'b': '10'},
"dict2": {'a': '25', 'b': '7'}
}
... or, in terms of your original post:
table = {
"dict1": dict1,
"dict2": dict2
}
From here, you should be able to invert the levels to obtain
invert = {
"a": {'dict1': '2', 'dict2': '25'},
"b": {'dict2': '10', 'dict2': '7'}
}
Is that enough to get your processing where it needs to be? Keeping the data in comprehensive dicts like this, will make it easier to iterate through the sub-dicts as needed.
As #Prune suggested, structuring your result as a nested dictionary will be easier:
{'a': {'dict1': '2', 'dict2': '25'}, 'b': {'dict1': '10', 'dict2': '7'}}
Which could be achieved with a dict comprehension:
{k: {"dict%d" % i: v2 for i, v2 in enumerate(v1, start=1)} for k, v1 in dd.items()}
If you prefer doing it without a comprehension, you could do this instead:
result = {}
for k, v1 in dd.items():
inner_dict = {}
for i, v2 in enumerate(v1, start=1):
inner_dict["dict%d" % i] = v2
result[k] = inner_dict
Note: This assumes you want to always want to keep the "dict1", "dict2",... key structure.

Is it possible to find and replace key without using pop() in python?

I've my dictionary elements in dic_name. var c has the key value to find in dic_name and var d is the new key to replace c.
dic_name[d]=dic_name.pop(c)
I've got the following output.
Enter the keyname you want to replace: e
Enter the new keyname value: z
ORIGINAL DICTIONARY {'q': '1', 'w': '2', 'e': '8', 'r': '4', 't': '5'}
NEW DICTIONARY {'q': '1', 'w': '2', 'r': '4', 't': '5', 'z': '8'}
Suppose if the key is not found, then it will generate key error. For that reason i've used the following code:
dic_name[d]=dic_name.pop(c,None)
But it creates new key with value as "None".
enter the keyname you want to replace: e
enter the new keyname value: r
ORIGINAL DICTIONARY {'q': '1', 'w': '2'}
NEW DICTIONARY {'q': '1', 'w': '2', 'r': None}
You need to be more clear on what you're trying to achieve here. Assuming that you want to ignore and do nothing if the key is not found, you can just do:
if c in dic_name:
dic_name[d] =dic_name.pop(c)
You can also use dict comprehension to create new dict and append replaced value on new dict
replace = 'e'
replace_with = 'z'
old_dict = {'q': '1', 'w': '2', 'e': '8', 'r': '4', 't': '5'}
new_dict = {i:j for i,j in old_dict.items() if i != replace}
new_dict[replace_with]=old_dict[replace]
print(new_dict)
There is nothing wrong with pop for this purpose. Simply handle the key not found condition:
try:
dic_name[d] = dic_name.pop(c)
except KeyError:
pass

How can I find a value is none in an object and delete the key and value with Python3?

I have an object and the I want to find the value is None.
And the next step I want to delete the key.
I try this way:
>>> obj = {'a': '1', 'b': '2', 'c': '3', 'd': None, 'e': '4', 'f': None }
>>> keys = list(obj.keys())
>>> for key in keys:
... if obj[key] == None:
... obj.pop(key, None)
>>> obj
{'a': '1', 'b': '2', 'c': '3', 'e': '4'}
Is there a better way to do this?
You could use a dictionary comprehension:
obj = {k: v for k, v in obj.items() if v is not None}
If you don't want to replace the dictionary wholesale (because perhaps you have other references to it), then your approach is sound, but can be made a little more efficient still by avoiding calling .keys(), and using del instead of dict.pop():
for key in list(obj):
if obj[key] is None:
del obj[key]
Testing for None should always be done with is; it's a singleton object.

Convert list to dictionary with duplicate keys using dict comprehension [duplicate]

This question already has answers here:
How can one make a dictionary with duplicate keys in Python?
(9 answers)
Closed 6 months ago.
Good day all,
I am trying to convert a list of length-2 items to a dictionary using the below:
my_list = ["b4", "c3", "c5"]
my_dict = {key: value for (key, value) in my_list}
The issue is that when a key occurrence is more than one in the list, only the last key and its value are kept.
So in this case instead of
my_dict = {'c': '3', 'c': '5', 'b': '4'}
I get
my_dict = {'c': '5', 'b': '4'}
How can I keep all key:value pairs even if there are duplicate keys.
Thanks
For one key in a dictionary you can only store one value.
You can chose to have the value as a list.
{'b': ['4'], 'c': ['3', '5']}
following code will do that for you :
new_dict = {}
for (key, value) in my_list:
if key in new_dict:
new_dict[key].append(value)
else:
new_dict[key] = [value]
print(new_dict)
# output: {'b': ['4'], 'c': ['3', '5']}
Same thing can be done with setdefault. Thanks #Aadit M Shah for pointing it out
new_dict = {}
for (key, value) in my_list:
new_dict.setdefault(key, []).append(value)
print(new_dict)
# output: {'b': ['4'], 'c': ['3', '5']}
Same thing can be done with defaultdict. Thanks #MMF for pointing it out.
from collections import defaultdict
new_dict = defaultdict(list)
for (key, value) in my_list:
new_dict[key].append(value)
print(new_dict)
# output: defaultdict(<class 'list'>, {'b': ['4'], 'c': ['3', '5']})
you can also chose to store the value as a list of dictionaries:
[{'b': '4'}, {'c': '3'}, {'c': '5'}]
following code will do that for you
new_list = [{key: value} for (key, value) in my_list]
If you don't care about the O(n^2) asymptotic behaviour you can use a dict comprehension including a list comprehension:
>>> {key: [i[1] for i in my_list if i[0] == key] for (key, value) in my_list}
{'b': ['4'], 'c': ['3', '5']}
or the iteration_utilities.groupedby function (which might be even faster than using collections.defaultdict):
>>> from iteration_utilities import groupedby
>>> from operator import itemgetter
>>> groupedby(my_list, key=itemgetter(0), keep=itemgetter(1))
{'b': ['4'], 'c': ['3', '5']}
You can use defaultdict to avoid checking if a key is in the dictionnary or not :
from collections import defaultdict
my_dict = defaultdict(list)
for k, v in my_list:
my_dict[k].append(v)
Output :
defaultdict(list, {'b': ['4'], 'c': ['3', '5']})

assigning a value from dictionary to equation

i want to assign a value to a string equation but i am stuck with the logic.
dic1 = {'d': '2', 'a': '1', 'c': '3', 'b': '2'}
equation_string = 'ab+cd'
i want to the output like:
'12+32' = 44
My Logic:
1 -> writing a for loop to assign the values to the string but i don't know how to skip '+' sign in the string.
for itr in range(0,len(equation_string)):
equation_String[itr] = dict1[equation_str[itr]]
In order to achieve it. You need to firstly replace the key in equation_string of dic1 with the corresponding value using string.replace(). When you made all the replacements within the string, execute the string expression using eval(). Below is the sample code:
>>> dic1 = {'d': '2', 'a': '1', 'c': '3', 'b': '2'}
>>> equation_string = 'ab+cd'
>>> for k, v in dic1.iteritems():
... equation_string = equation_string.replace(k, v)
...
>>> equation_string
'12+32' # Updated value of equation_string
>>> eval(equation_string)
44

Categories

Resources