creating a dict based on two python dicts - python-3.x

I have two python dicts:
payload = {"key1":{"a":"1"},"key2":{"b":"2","c":"3"}}
and
data = {"1":"John","2":"Jacob"}
I would like my output to be:
{"key1":{"a":"John"},"key2":{"b":"Jacob","c":""}}
Any method that I try correctly prints the values, but does not update the output dictionary.

You can do something like this using dict comprehension :
payload = {"key1":{"a":"1"},"key2":{"b":"2","c":"3"}}
data = {"1":"John","2":"Jacob"}
final = {k: {i:data[j] if j in data.keys() else "" for i, j in payload[k].items()} for k in payload}
print(final)
Output:
{'key2': {'b': 'Jacob', 'c': ''}, 'key1': {'a': 'John'}}

There is no single method for this I am aware of, but you can use:
for k, v in payload.viewitems():
payload[k] = {}
for kv, vv in v.viewitems():
payload[k][kv] = data.get(vv, "")
if you then inspect payload it has the contents you are after:
{'key2': {'c': '', 'b': 'Jacob'}, 'key1': {'a': 'John'}}

Related

Python: Convert 2d list to dictionary with indexes as values

I have a 2d list with arbitrary strings like this:
lst = [['a', 'xyz' , 'tps'], ['rtr' , 'xyz']]
I want to create a dictionary out of this:
{'a': 0, 'xyz': 1, 'tps': 2, 'rtr': 3}
How do I do this? This answer answers for 1D list for non-repeated values, but, I have a 2d list and values can repeat. Is there a generic way of doing this?
Maybe you could use two for-loops:
lst = [['a', 'xyz' , 'tps'], ['rtr' , 'xyz']]
d = {}
overall_idx = 0
for sub_lst in lst:
for word in sub_lst:
if word not in d:
d[word] = overall_idx
# Increment overall_idx below if you want to only increment if word is not previously seen
# overall_idx += 1
overall_idx += 1
print(d)
Output:
{'a': 0, 'xyz': 1, 'tps': 2, 'rtr': 3}
You could first convert the list of lists to a list using a 'double' list comprehension.
Next, get rid of all the duplicates using a dictionary comprehension, we could use set for that but would lose the order.
Finally use another dictionary comprehension to get the desired result.
lst = [['a', 'xyz' , 'tps'], ['rtr' , 'xyz']]
# flatten list of lists to a list
flat_list = [item for sublist in lst for item in sublist]
# remove duplicates
ordered_set = {x:0 for x in flat_list}.keys()
# create required output
the_dictionary = {v:i for i, v in enumerate(ordered_set)}
print(the_dictionary)
""" OUTPUT
{'a': 0, 'xyz': 1, 'tps': 2, 'rtr': 3}
"""
also, with collections and itertools:
import itertools
from collections import OrderedDict
lstdict={}
lst = [['a', 'xyz' , 'tps'], ['rtr' , 'xyz']]
lstkeys = list(OrderedDict(zip(itertools.chain(*lst), itertools.repeat(None))))
lstdict = {lstkeys[i]: i for i in range(0, len(lstkeys))}
lstdict
output:
{'a': 0, 'xyz': 1, 'tps': 2, 'rtr': 3}

The problem of using {}.fromkey(['k1','k2'],[]) and {'k1':[],'k2':[]}

list1 = [99,55]
dict1 = {'k1':[],'k2':[]}
for num in list1:
if num > 77:
dict1['k1'].append(num)
else:
dict1['k2'].append(num)
print(dict1)
{'k1':[99],'k2':[55]}
But when I replaced dict1 = {'k1':[],'k2':[]} to {}.fromkeys(['k1','k2'],[]) , the result became {'k1': [99, 55], 'k2': [99, 55]}
why this happens? I really have no idea.
This happens because you are passing the same list object to both keys. This is the same situation as when you create an alias for a variable:
a = []
b = a
a.append(55)
b.append(99)
print(b)
prints [55, 99] because it is the same list instance.
If you want to make it more concise from a list of keys to initialize with empty list, you can do this:
dict1 = {k: [] for k in ('k1', 'k2')}
This will create a new list instance for every key.
Alternatively, you can use defaultdict
from collections import defaultdict
list1 = [99,55]
dict1 = defaultdict(list)
for num in list1:
if num > 77:
dict1['k1'].append(num)
else:
dict1['k2'].append(num)
print(dict1)
Also works.
The fromKeys() can also be supplied with a mutable object as the default value.
if we append value in the original list, the append takes place in all the values of keys.
example:
list1 = ['a', 'b', 'c', 'd']
list2 = ['SALIO']
dict1 = dict.fromkeys(list1, list2)
print(dict1)
output:
{'a': ['SALIO'], 'b': ['SALIO'], 'c': ['SALIO'], 'd': ['SALIO']}
then you can use this:
list1 = ['k1', 'k2']
dict1 = {'k1':[],'k2':[]}
list2 =[99,55]
for num in list2:
if num > 77:
a = ['k1']
dict1 = dict.fromkeys(a, [num])
else:
b = ['k2']
dict2 = dict.fromkeys(b,[num] )
res = {**dict1, **dict2}
print(res)
output:
{'k1': [99], 'k2': [55]}
You can also use the python code to merge dict code:
this function:
def Merge(dict1, dict2):
return(dict2.update(dict1))
then:
print(Merge(dict1, dict2)) #This return None
print(dict2) # changes made in dict2

How to check if multiple keys exists in nested (all) dictionary?

To check if 'b' & 'c' exists in 'a' & 'b'.
test = {
'a': {
'b': [1234],
'c': 'some_value'
},
'd': {
'b': [5678],
'c': ''
}
}
Approach1: works as below but not great implementation if nested dictionary are huge in number. And also, You can't exactly notify which element doesn't exist. Let's say, 'c' not in 'a' , 'b' not in 'd' & 'c' not in 'd' . In this case, it fails at second statement (but it doesn't notify that 3rd & 4th statements also fail). I need to get, which all doesn't exist.
try:
v1 = test['a']['b']
v2 = test['a']['c']
v3 = test['d']['b']
v4 = test['d']['c']
except Exception as err:
print(err)
Approach2:
for k,v in test.items():
if 'b' not in v:
print("'b' doesn't exist in {}".format(test[k][v]))
if 'c' not in v:
print("'c' doesn't exist in {}".format(test[k][v]))
Approach1 and Approach2 seem to be not great. Any other better ways to handle it ?
If there are only two levels of nest, could you please try to count occurence of keys in lower-level dicts?
For example:
counter = {}
for el in test.keys():
for subkey in test.get(el).keys():
if subkey not in counter.keys():
counter[subkey] = 1.0
else:
counter[subkey] += 1.0
it'll return
{'b': 2.0, 'c': 2.0}
based on that you can identify duplicated values in your nested keys.
You could then use set to saw on which keys duplicates exist:
dupe keys
counter = {k : v for k, v in counter.items() if v > 1}
#get only values with dupe records
{k:v for k, v in test.items() if len(set(counter.keys()).intersection(v)) > 0}
> {'a': {'b': [1234], 'c': 'some_value'}, 'd': {'b': [5678], 'c': ''}}

Merging list of dicts in python

I have the dict in python in the following format:
dict1 = [{'Name':'a', 'value':20},{'Name':'b', 'value':10},{'Name':'c', 'value':15}]
I want output something like this:
dict2 = {'a':20, 'b':10, 'c':15 }
How to do it ?
I think you can do it with for loop efficiently.
Check this:
dict1 = [{'Name':'a', 'value':20},{'Name':'b', 'value':10},{'Name':'c', 'value':15}]
dict2 = dict()
for a in range(len(dict1)):
dict2[dict1[a].get('Name')] = dict1[a].get('value')
print(dict2)
Output:
{'a': 20, 'b': 10, 'c': 15}
This is the easy way:
dict1 = [{'Name':'a', 'value':20},{'Name':'b', 'value':10},{'Name':'c', 'value':15}]
dict2={dc['Name']:dc['value'] for dc in dict1}

How can I write a program in Python Dictionary that prints repeated keys values?

This is my INPUT:
dic1 = {'a':'USA', 'b':'Canada', 'c':'France'}
dic2 = {'c':'Italy', 'd':'Norway', 'e':'Denmark'}
dic3 = {'e':'Finland', 'f':'Japan', 'g':'Germany’}
I want output something like below:
{'g': 'Germany', 'e': [‘Denmark’,’Finland'], 'd': 'Norway', 'c': ['Italy’,'France', 'f': 'Japan', 'b': 'Canada', 'a': 'USA'}
That is programing - you think the steps you need to get to your desired results, and write code to perform these steps, one at a time.
A funciton like this can do it:
def merge_dicts(*args):
merged = {}
for dct in args:
for key, value in dct.items():
if key not in merged:
merged[key] = []
merged[key].append(value)
return merged

Resources