How to create a nested dictionary - python

so I have some problems with my dictionaries in python. For example I have dictionary like below:
d1 = {123456:xyz, 892019:kjl, 102930491:{[plm,kop]}
d2= {xyz:987, kjl: 0902, plm: 019240, kop:09829}
And I would like to have nested dictionary that looks something like that.
d={123456 :{xyz:987}, 892019:{kjl:0902}, 102930491:{plm:019240,kop:09829}}
is this possible? I was searching for nested dictionaries but nothing works for me.

You just need to loop through d1 and assign the correct values from d2.
Code:
d1 = {123456:'xyz', 892019:'kjl', 102930491:['plm','kop']}
d2 = {'xyz':987, 'kjl': 902, 'plm': 19240, 'kop':9829}
result = {}
for k, v in d1.items():
if isinstance(v, list):
result[k] = {k: d2.get(k) for k in v}
else:
result[k] = {v: d2.get(v)}
print(result)
Output:
{123456: {'xyz': 987}, 892019: {'kjl': 902}, 102930491: {'plm': 19240, 'kop': 9829}}
The above uses isintance() to check if the value is a list, so you can loop over it and assign the correct values from d2. It also uses dict.get() to ensure None is added if a KeyError was encountered when searching for a key in d2.
One-liner:
{k: {k: d2.get(k) for k in v} if isinstance(v, list) else {v: d2.get(v)} for k, v in d1.items()}
But this becomes messy and less maintainable.

First, you hate to put brackets around your keys and values.
d1 = {'123456':'xyz', '892019':'kjl', '102930491':'plm'}
d2= {'xyz':'987', 'kjl':'0902', 'plm':'019240', 'kop':'09829'}
Then I suggest you do a for loop
for key, value in d1.iter():
d1[key] = d2[value]
I have ignored your {[plm,kop]} thing. But it wont be difficult to implement it if you understand this first example.

Related

How to reverse dictionary items and list keys grouped by common values [duplicate]

This question already has answers here:
Dictionary comprehension for swapping keys/values in a dict with multiple equal values
(3 answers)
Closed 2 years ago.
I have a dictionary that I want to group by the common values:
init_dict = {'00001': 'string1', '00002': 'string2', '00003': 'string1', '00004': 'string3', '00005': 'string2'}
I want to create a new dictionary that groups the values and lists the keys like this:
new_dict = {'string1': ['00001', '00003'], 'string2':['00002', '00004'], 'string3': ['00004']}
I tried many things and this is the closest I can get.
lookup = 'string1'
all_keys = []
for k, v in init_dict.items():
if v == lookup:
all_keys.append(k)
print(all_keys)
This produces the first list: ['00001', '00003'] so I thought I could somehow loop through a list of lookup values but can't since I'm working with strings. Is there a way to do this and is there a way that is relatively efficient because my initial dictionary has 53,000 items in it. Any help would be much appreciated as I've been trying different things for hours.
Use a defaultdict, specifying a list as default argument, and append the corresponding values from the dictionary:
from collections import defaultdict
d = defaultdict(list)
for k,v in init_dict.items():
d[v].append(k)
print(d)
defaultdict(list,
{'string1': ['00001', '00003'],
'string2': ['00002', '00005'],
'string3': ['00004']})
You can use defaultdict
result = defaultdict(list)
for k, v in init_dict.items():
result[v].append(k)
or itertools.groupby
result = {k: [x[0] for x in v] for k, v in
groupby(sorted(init_dict.items(), key=lambda kv: kv[1]), key=lambda kv: kv[1])}
You can also use a normal dict (instead of defaultdict):
new_dict = {}
for key, val in init_dict.items():
if val in new_dict:
new_dict[val].append(key)
else:
new_dict[val] = []
new_dict[val].append(key)
Output:
new_dict = {'string1': ['00001', '00003'],
'string2': ['00002', '00005'],
'string3': ['00004']}

Constructing Key:Value pair from list comprehension in Python

I am trying to extend some code.
What works:
pretrained_dict = {k: v for k, v pretrained_dict.items if k in model_dict}
However, if I extend it to:
pretrained_dict = {k: v if k in model_dict else k1:v1 for k, v, k1, v1 in zip(pretrained_dict.items(), model_dict.items()) }
The code fails, If I put the else at the end it still fails:
pretrained_dict = {k: v if k in model_dict for k, v, k1, v1 in zip(pretrained_dict.items(), model_dict.items()) else k1:v1}
^
SyntaxError: invalid syntax
How can I construct the key value pair using an if else condition over two lists?
You can use a ChainMap to achieve what you want without having to use comprehensions at all
from collections import ChainMap
pretrained_dict = ChainMap(pretrained_dict, model_dict)
This returns a dictionary-like object that will lookup keys in pretrained_dict first and if it is not present then lookup the key in model_dict
The reason that the second comprehension doesn't work is that the ternary operator only applies in the value. Luckily, both cases apply to the same key, so you can actually simplify the syntax a little. If that was not the case, you'd have to use two separate ternary operators or a for loop.
Another problem is that you don't show the grouping in your loop variables. dict.items yields tuples, and you have to make it clear how to unpack them.
So:
pretrained_dict = {k: v if k in model_dict else v1 for (k, v), (k1, v1) in zip(pretrained_dict.items(), model_dict.items())}
However, this won't actually do any of the lookup that you want. If your goal is to accept keys from pretrained_dict into model_dict in bulk, then you need to use model_dict.update with the appropriate keys. Zipping two dictionaries together is generally meaningless, since they won't have the same keys, and so it's unclear what the result would even be. Using a comprehension here isn't keeping with the literal requirement here either, since it necessarily means replacing rather than updating. In either case, your result should affect model_dict, not pretrained_dict.
Here is how you would do an update:
model_dict.update((k, v) for k, v in pretrained_dict.items() if k in model_dict)

How to increment values for each key in dict?

In Python, how to iterate a dict and increment values of each key?
D = {k1:1, k2:2}
I want D to be {k1:2, k2:3}.
You can use a dict comprehension to increment each value, then assign it back
>>> {k: v+1 for k,v in D.items()}
{'k1': 2, 'k2': 3}
You can either modify (also called "mutate") the dictionary D:
for k in D.keys():
D[k] = D[k] + 1
Or you can create a new dictionary and re-assign D to it:
D = { k: v+1 for k, v in D.items() }
The difference will become apparent if something else points at D, or if D is very large and takes longer to re-create than to update in-place.
D = {"k1":1, "k2":2}
for i in D:
D[i] += 1
print(D)
Seems to do the trick, I wasnt sure on the k1 / k2 so i made them strings for testing
I have another solution for you, I hope it is useful.
for key in D:
D[key] +=1

Find non-Empty value in dict

I have a dict like this:
d = {'first':'', 'second':'', 'third':'value', 'fourth':''}
and I want to find first non-empty value (and it's name, in this example 'third'). There may be more than one non-empty value, but I only want the first one I find.
How can I do this?
Use an OrderedDict which preserves the order of elements. Then loop over them and find the first that isn't empty:
from collections import OrderedDict
d = OrderedDict()
# fill d
for key, value in d.items():
if value:
print(key, " is not empty!")
You could use next (dictionaries are unordered - this somewhat changed in Python 3.6 but that's only an implementation detail currently) to get one "not-empty" key-value pair:
>>> next((k, v) for k, v in d.items() if v)
('third', 'value')
Like this?
def none_empty_finder(dict):
for e in dict:
if dict[e] != '':
return [e,dict[e]]
d = {'first':'', 'second':'', 'third':'value', 'fourth':''}
for k, v in d.items():
if v!='':
return k, v
Edit 1
from the comment if the value is None or '' we better use if v: instead of if v!=''. if v!='' only check the '' and skip others
You can find empty elements and make a list of them:
non_empty_list = [(k,v) for k,v in a.items() if v]
By using list comprehension, you can list all the non-empty values and then fetch the 0th value:
[val for key, val in d.items() if val][0]

Efficient way of removing keys of certain prefix from python dictionary

I have a python dictionary which looks something like this;
{'Prefix_1':'12', 'Prefix_2':'11', 'Prefix_3':'14', '1':'241', '2':'312', '3':'421'
}
I want to remove the key-value pairs of those with keys that start with 'Prefix'. The result should be a dictionary that look like this;
{'1':'241', '2':'312', '3':'421'
}
My current way of doing so is to remove each pair one by one by using del dictionary['Prefix_X']. What are more efficient ways of doing so?
I am using python 2.7
Since the other answers all use dict comprehension to create a new dict and leave the original dict untouched, I'll give one that change the dict in place:
for k in d.keys():
if k.startswith('Prefix'):
d.pop(k)
Is there a better way?
Let's say there are N keys in the dictionary, to find all keys with the given prefix, you'll have to iterate over all the keys, and this is of O(N) time complexity.
Then you'll need to delete them one by one, in the worst case all of them are with the given prefix, so this is also of O(N) time complexity.
The total time complexity if O(N).
You could use a dict comprehension over the original dictionary:
D = {'Prefix_1':'12', 'Prefix_2':'11', 'Prefix_3':'14', '1':'241', '2':'312', '3':'421'
NewDict = {k: D[k] for k in D if not k.startswith('Prefix')}
NewDict
{'2': '312', '3': '421', '1': '241'}
use dictionary comprehensions
{k:v for k, v in d.items() if not k.startswith('Prefix')}
In [44]: {k:v for k, v in d.items() if not k.startswith('Prefix')}
Out[44]: {'1': '241', '2': '312', '3': '421'}
>>> z = {'Prefix_1':'12', 'Prefix_2':'11', 'Prefix_3':'14', '1':'241', '2':'312', '3':'421'}
>>> {k:v for k,v in z.items() if not k.startswith('Prefix')}
{'1': '241', '3': '421', '2': '312'}
d1 = {'Prefix_1':'12', 'Prefix_2':'11', 'Prefix_3':'14', '1':'241', '2':'312', '3':'421'}
d2 = {k: v for k, v in d1.iteritems() if not k.startswith('Prefix')}
print d1
print d2
Try to this.
for key in d.keys():
if 'Prefix' in key:
d.pop(key)

Categories

Resources