Append value to a list which in nested dictionary - python

Basically I need to populate d3 from d2 and d1
d1 = {'Spain':['Madrid,'Barcelona'],'France':['Paris','Nice'],'Germany':['Dortmund','Berlin']}
d2 = {'Madrid':[1,2]'Barcelona':[2],'Paris':[3,4],'Nice':[4],'Dortmund':[5],'Berlin':[6]}
Desired output d3 is as follows:
d3 = {'Spain':{'Madrid':[1,2]},{'Barcelona':[2]},'France':{'Paris':[3,4]},{'Nice':[4]},'Germany':{'Dortmund':{[5]},{'Berlin':[6]}}
I tried following but no luck, I am stuck
l = []
def getKeysByValue(dictOfElements, valueToFind):
listOfKeys = list()
listOfItems = dictOfElements.items()
for item in listOfItems:
if item[1] == valueToFind:
listOfKeys.append(item[0])
return listOfKeys
for i in d2.keys():
for j in d1.values():
if i in j:
name = str(getKeysByValue(d1,j))
l.append({i:name2})
d3[name] = l
print(d3)

You can use a dict comprehension to achieve this.
d1 = {'Spain': ['Madrid','Barcelona'],
'France': ['Paris','Nice'],
'Germany': ['Dortmund','Berlin']}
d2 = {'Madrid': [1,2],
'Barcelona': [2],
'Paris': [3,4],
'Nice': [4],
'Dortmund': [5],
'Berlin':[6]}
d3 = {k: {city: d2[city] for city in v} for k, v in d1.items()}
It is iterating through the keys and values of d1. For every key, the value is a dictionary with each element in the value list as the key, and the d2 value of that key as the value.

You can simply create d3 like this:
d1 = {'Spain':['Madrid','Barcelona'],'France':['Paris','Nice'],'Germany':['Dortmund','Berlin']}
d2 = {'Madrid':[1,2],'Barcelona':[2],'Paris':[3,4],'Nice':[4],'Dortmund':[5],'Berlin':[6]}
d3 = {country:{city:d2[city] for city in cities} for (country,cities) in d1.items()}
print(d3)
Output:
{'Spain': {'Madrid': [1, 2], 'Barcelona': [2]}, 'France': {'Paris': [3, 4], 'Nice': [4]}, 'Germany': {'Dortmund': [5], 'Berlin': [6]}}
I have taken the liberty of correcting your data sources.

d1 = {'Spain':['Madrid','Barcelona'],'France':['Paris','Nice'],'Germany':['Dortmund','Berlin']}
d2 = {'Madrid':[1,2], 'Barcelona':[2],'Paris':[3,4],'Nice':[4],'Dortmund':[5],'Berlin':[6]}
d3 = {}
for k, v in d1.items():
data = {}
for item in v:
if item in d2: # to escape from an KeyError from d2 dictionary
data[item] = d2[item]
d3[k] = data

Related

Python: Merge 2 dictionaries and add 0 if key is empty

I have 2 dicts as follows:
d1 = {a:2, b:4}
d2 = {a:13, b:3, c:5}
How to merge these two and add 0 if one key is empty?
The result should be
= {a:[2,13], b:[4,3], c:[0,5]}
I tried to use this
d1 = {'a':2, 'b':4}
d2 = {'a':13, 'b':3, 'c':5}
dd = defaultdict(list)
for d in (d1, d2):
for key, value in d.items():
dd[key].append(value)
but I don't know how to add 0, I'm really new to programming.
You can get the list of keys then generate the required dictionary by using dict.get and default value as 0
d1 = {'a':2, 'b':4}
d2 = {'a':13, 'b':3, 'c':5}
keys = set((*d1.keys(), *d2.keys()))
new_dict = {k: [d.get(k, 0) for d in [d1, d2]] for k in keys}
print(new_dict) #{'a': [2, 13], 'b': [4, 3], 'c': [0, 5]}
Use below code.
d1 = {'a':2, 'b':4}
d2 = {'a':13, 'b':3, 'c':5}
keys = set((*d1.keys(), *d2.keys()))
result={}
for k in keys:
result[k]=list((d1.get(k, 0), d2.get(k,0)))
print(result)#{'a': [2, 13], 'b': [4, 3], 'c': [0, 5]}

Python Dictionary - How to find all keys with the lowest amount of unique value?

Let's say I have a dictionary:
dict = {'a' : [1, 2], 'b' : [1], 'c' : [3, 3, 3]}
How do I find which keys have the lowest amount of unique values? In this case, it would be the dictionary with the keys 'b' and 'c' as they each only have 1 unique value.
You can create an inverted mapping using collections.defaultdict and access the keys corresponding to the least number of unique values:
from collections import defaultdict
d = {'a' : [1, 2], 'b' : [1], 'c' : [3, 3, 3]}
# dictionary mapping len of unique values to corresponding key
d2 = defaultdict(list)
for k in d:
d2[len(set(d[k]))].append(k)
print (d2)
# defaultdict(list, {2: ['a'], 1: ['b', 'c']})
print (d2[min(d2)])
# ['b', 'c']
You can do the following:
d = {'a' : [1, 2], 'b' : [1], 'c' : [3, 3, 3]} #avoid using 'dict' as name of dictionary
temp={k:len(set(v)) for k, v in d.items()} #get the count of unique values for each key
res=[i for i in temp if temp[i]==min(temp.values())] #get the keys with min value
>>> print(res)
['b', 'c']
Try like this:
d = {'a' : [1, 2], 'b' : [1], 'c' : [3, 3, 3]}
ml={i:len(set(m)) for i,m in d.items()}
res={i:d[i] for i,z in ml.items() if z==min(ml.values())}
print(res)
You can take the following three steps
# Create a dictionary d with format {key: number of unique values}
d = {key: len(set(value)) for key, value in dict.items()}
# Find the minimum value in this dictionary
min_value = min(d.values())
# Find all the keys with value equal to the minimum
min_list = [key for key, value in d.items() if value == min_value]
The result will be a list containing b and c in your example
You could use an auxiliary dict or comprehension as in other answers if you need to do further processing, otherwise IMO no need for anything fancy, a simple for loop should do the trick, using set() conversion as a quick way to count unique values
As a minor aside, it's recommended not to use dict as your dict variable name since it's a reserved keyword in python and it will shadow use of that keyword
def keys_with_fewest_uniq_values(d):
min_num_uniq, min_keys = None, []
for key, val in dict.items():
num_uniq = len(set(val))
if min_num_uniq is None or num_uniq < min_num_uniq:
min_num_uniq = num_uniq
min_keys = [key]
elif num_uniq == min_num_uniq:
min_keys.append(key)
return min_keys
>> my_dict = {'a' : [1, 2], 'b' : [1], 'c' : [3, 3, 3]}
>> print(keys_with_fewest_uniq_values(my_dict))
['b','c']

How to 'deep-merge' dicts?

Imagine the following dicts:
a = {'key1': {'subkey1': [1, 2, 3]}}
b = {'key1': {'subkey2': [1, 2, 3]}}
I'd like to merge them to get
c = {'key1': {'subkey1': [1, 2, 3],
'subkey2': [1, 2, 3]}}
Extra nice would be a solution that returns deep-copies from a and b which I can alter without altering a or b.
c = {**a, **b}
looks nice but seems to be the same as c = copy(a).update(b) which returns same as b in my case because key1 gets overwritten by the update.
You can of course do this by hand like this (found in another answer):
def combine_dict(map1: dict, map2: dict):
def update(d: dict, u: dict):
for k, v in u.items():
if isinstance(v, collections.Mapping):
r = update(d.get(k, {}), v)
d[k] = r
else:
d[k] = u[k]
return d
_result = {}
update(_result, map1)
update(_result, map2)
return _result
But we have Python 3.5 now - maybe things have changed?
You need recursion to accomplish this. Luckily milanboers on GitHub saved us from hours of work and possible brain damage.
def deep_merge(dict1: dict, dict2: dict) -> dict:
""" Merges two dicts. If keys are conflicting, dict2 is preferred. """
def _val(v1, v2):
if isinstance(v1, dict) and isinstance(v2, dict):
return deep_merge(v1, v2)
return v2 or v1
return {k: _val(dict1.get(k), dict2.get(k)) for k in dict1.keys() | dict2.keys()}
a = {'key1': {'subkey1': [1, 2, 3]}}
b = {'key1': {'subkey2': [1, 2, 3]}}
a = deep_merge(a, b)
print(a)
Results in:
{'key1': {'subkey2': [1, 2, 3], 'subkey1': [1, 2, 3]}}

Is there any pythonic way to combine two dicts (making a list for common values)?

For example, I have two dicts.
A = {'a':1, 'b':10, 'c':2}
B = {'b':3, 'c':4, 'd':10}
I want a result like this:
{'a':1, 'b': [10, 3], 'c':[2, 4], 'd':10}
If a key appears in both the dicts, I want to list of both the values.
I'd make all values lists:
{k: filter(None, [A.get(k), B.get(k)]) for k in A.viewkeys() | B}
using dictionary view objects.
Demo:
>>> A = {'a':1, 'b':10, 'c':2}
>>> B = {'b':3, 'c':4, 'd':10}
>>> {k: filter(None, [A.get(k), B.get(k)]) for k in A.viewkeys() | B}
{'a': [1], 'c': [2, 4], 'b': [10, 3], 'd': [10]}
This at least keeps your value types consistent.
To produce your output, you need to use the set intersection and symmetric differences between the two dictionaries:
dict({k: [A[k], B[k]] for k in A.viewkeys() & B},
**{k: A.get(k, B.get(k)) for k in A.viewkeys() ^ B})
Demo:
>>> dict({k: [A[k], B[k]] for k in A.viewkeys() & B},
... **{k: A.get(k, B.get(k)) for k in A.viewkeys() ^ B})
{'a': 1, 'c': [2, 4], 'b': [10, 3], 'd': 10}
In Python 3, dict.keys() is a dictionary view, so you can just replace all .viewkeys() calls with .keys() to get the same functionality there.
I would second the notion of Martijn Pieters that you problably want to have the same type for all the values in your result dict.
To give a second option:
you could also use the defaultdict to achieve your result quite intuitively.
a defaultdict is like a dict, but it has a default constructor that is called if the key doesn't exist yet.
so you would go:
from collections import defaultdict
A = {'a':1, 'b':10, 'c':2}
B = {'b':3, 'c':4, 'd':10}
result = defaultdict(list)
for d in [A, B]:
for k, v in d.items():
result[k].append(v)
then in a later stage you still easily add more values to your result.
you can also switch to
defaultdict(set)
if you don't want duplicate values

Filter a dict of dict

I new in Python and I am not sure it is a good idea to use dict of dict but here is my question.
I have a dict of dict and I want to filter by the key of the inside dict:
a ={ 'key1' : {'id1' :[0,1,2] , 'id2' :[0,1,2], 'id3' :[4,5,6]}
'key2' : {'id3' :[0,1,2] , 'id4' :[0,1,2]}
'key3' : {'id3' :[0,1,2] , 'id1' :[4,5,6]}
}
For exemple , I want to filter by 'id1' to have :
result = { 'key1' : {'id1' :[0,1,2] }
'key3' : {'id1' :[4,5,6]}
}
I have tried the filter method by I get all the value:
r = [('key1' ,{'id1' :[0,1,2] , 'id2' :[0,1,2], 'id3' :[4,5,6]})
('key3' , {'id3' :[0,1,2] , 'id1' :[4,5,6]})
]
Furthermore the filter method returns a list and I want to keep the format as a dict.
Thanks in advance
Try this:
>>> { k: v['id1'] for k,v in a.items() if 'id1' in v }
{'key3': [4, 5, 6], 'key1': [0, 1, 2]}
For Python 2.x you might prefer to use iteritems() instead of items() and you'll still need a pretty recent python (2.7 I think) for a dictionary comprehension: for older pythons use:
dict((k, v['id1']) for k,v in a.iteritems() if 'id1' in v )
If you want to extract multiple values then I think you are best to just write the loops out in full:
def query(data, wanted):
result = {}
for k, v in data.items():
v2 = { k2:v[k2] for k2 in wanted if k2 in v }
if v2:
result[k] = v2
return result
giving:
>>> query(a, ('id1', 'id2'))
{'key3': {'id1': [4, 5, 6]}, 'key1': {'id2': [0, 1, 2], 'id1': [0, 1, 2]}}
According to the precision you gave to Duncan, here is another filtering on a list using dictionary comprehension:
>>> my_list = ['id1', 'id2']
>>> {k1 : {k2: v2 for (k2, v2) in a[k1].iteritems() if k2 in my_list} for k1 in a}
{'key3': {'id1': [4, 5, 6]}, 'key2': {}, 'key1': {'id2': [0, 1, 2], 'id1': [0, 1, 2]}}
EDIT: you can also remove empty values with another dict compreehension, but that "begins" to be difficult to read... :-)
>>> {k3: v3 for k3, v3 in {k1 : {k2: v2 for (k2, v2) in a[k1].iteritems() if k2 in my_list} for k1 in a}.iteritems() if v3}
{'key3': {'id1': [4, 5, 6]}, 'key1': {'id2': [0, 1, 2], 'id1': [0, 1, 2]}}
You can do with a dictionary comprehension:
def query(data, query):
return {key : {query : data[key][query]}
for key in data if query in data[key]}
You have to look at each entry of the dictionary, which can cost a lot of time if you have many entries or do this a lot. A database with a index can speed this up.
field = 'id1'
dict( (k,{field: d[field]}) for k,d in a.items() if field in d)

Categories