Dictionary comprehension with conditional - python

So I'm wondering if anyone can help me out with this issue I'm having.
Lets assume I have a dictionary:
d = {1: {2: 3}, 4: 5}
I want to create a dictionary of any contained dictionaries:
wanted_result = {2: 3}
what I am trying is this:
e = {inner_key: d[key][inner_key] for key in d.keys() for inner_key in d[key].keys() if isinstance(d[key], dict)}
However this is causing me to get an error saying that ints don't have keys, which I know, but I thought my conditional would exclude say 4 from my example from being included in the comprehension.

d = {1: {2: 3}, 4: 5, 6: {7: 8}}
s = {k: v for elem in d.values() if type(elem) is dict for k, v in elem.items()}
>> {2: 3, 7: 8}

In this case, I would recommend you a for-loop and the update method:
d = {1: {2: 3}, 4: 5, 6: {7: 8}}
inner_dicts = {}
for val in d.values():
if type(val) is dict:
inner_dicts.update(val)
print inner_dicts
# {2: 3, 7: 8}

My first idea was something like this:
d = {1: {2: 3}, 4: 5, 6: {7: 8}}
generator = (x.items() for x in d.itervalues() if type(x) == dict)
s = dict(sum( generator, list() ))
# s = {2: 3, 7: 8}
But, in order to avoid letting sum() construct a large temporary list of all the items() you may use itertools.chain and iteritems() instead:
# chain "concatenates" iterables
from itertools import chain
d = {1: {2: 3}, 4: 5, 6: {7: 8}}
s = dict(chain( *(x.iteritems() for x in d.itervalues() if type(x) == dict) ))
# s = {2: 3, 7: 8}
You should be aware of edge cases. Especially if identical keys are in the part-dictionaries these will necessarily collapse somehow.
If you also want to support subclasses of dict to be collected from your d.values(), you may indeed want to use isinstance instead of type. See this question for details.

The following list comprehension will return each value that is a dict:
>>> d = {1: {2: 3}, 4: 5}
>>> [d[i] for i in d.keys() if isinstance(d[i],dict)]
[{2: 3}]

d = {1: {2: 3}, 4: 5,'j':{7:8}}
e={y:d[x][y] for x in d if isinstance(d[x],dict) for y in d[x]}
print(e)
{2: 3, 7: 8}

Other way using lambda
(lambda x: {k:v for x in d.values() if type(x) == dict for k,v in x.items()})(d)

Related

How to add an existing dictionary as a nested dictionary to an already existing dictionary in python?

In python3, I have 2 dictionaries, dict1 and dict2 that are both populated with key/value pairs. I want to create a new dictionary dict3 and add both dict1 and dict2 as nested dictionaries to it. I cant BELIEVE how much time Ive wasted trying to google a solution. I find tutorial after tutorial about how to create nested dictionaries from scratch but nothing about adding an existing dictionary nested to another dictionary.
IIUC:
dict1={1:2,3:4}
dict2={5:6,7:8}
dict3=dict(list(dict1.items())+[('dict2', dict2)])
print(dict3)
Output:
{1: 2, 3: 4, 'dict2': {5: 6, 7: 8}}
Or if you want to add the two dictionary:
dict1={1:2,3:4}
dict2={5:6,7:8}
dict3=dict([('dict1', dict1)]+[('dict2', dict2)])
print(dict3)
#Output:
#{'dict1': {1: 2, 3: 4}, 'dict2': {5: 6, 7: 8}}
Another ways:
#first scenario
dict1={1:2,3:4}
dict2={5:6,7:8}
dict3={**dict1}
dict3.update({'dict2':dict2})
print(dict3)
#Output:
#{1: 2, 3: 4, 'dict2': {5: 6, 7: 8}}
#second scenario
dict1={1:2,3:4}
dict2={5:6,7:8}
dict3={}
dict3.update({'dict1':dict1,'dict2':dict2})
print(dict3)
#Output:
#{'dict1': {1: 2, 3: 4}, 'dict2': {5: 6, 7: 8}}

convert a normal sequence dictionary into reversed triply ordered dictionary

I want to convert my dictionary to a triply ordered reversed dictionary.
my dictionary is {1: 1, 3: 3, 5: 6, 6: 6}
I have already tried using nested dictionaries, but i am not sure how to get the required output.
Dict1 = list(Dict)
Dict2['Dict1'] = Dict
print(Dict2)
The output should be {1: {1: [1], 3: [3]}, 2: {6: [5, 6]}}
if i define a different dictionary, i should get different triply ordered dictionary.
Can someone please help me with this?
from collections import defaultdict
orig_d = {1: 1, 3: 3, 5: 6, 6: 6}
new_d = defaultdict(list)
for k, v in orig_d.items():
new_d[v].append(k)
final_d = defaultdict(dict)
for cnt, (k, v) in sorted((len(v), (k, v)) for k, v in new_d.items()):
final_d[cnt][k] = v
print(dict(final_d))
Prints:
{1: {1: [1], 3: [3]}, 2: {6: [5, 6]}}

Map a dictionary on a list of dictionaries

I have a dictionary Items
Items = {1: 1, 2: 2, 3: 2, 4: 2, 5: 2, 6: 3, 7: 4, 8: 5}
I want to map the values of Items on a list of dictionaries named loaded
loaded = [{6: [4, 1, 3]}, {1: [5]}, {10: [8, 6]}, {6: [7]}, {2: [2]}]
such that I get this as my outcome:
u_loaded = [{6: [2, 1, 2]}, {1: [2]}, {10: [5, 3]}, {6: [4]}, {2: [2]}]
I tried running loops and replacing the values if a match is found but it's not working
for i in loaded_list:
for k,v in i.items():
for j in v:
for a,b in pid_itemid_dic.items():
if j==a:
j=b
u_loaded = [{k:[Items[a] for a in v] for k,v in l.items()} for l in loaded]
print(u_loaded)
Output
[{6: [2, 1, 2]}, {1: [2]}, {10: [5, 3]}, {6: [4]}, {2: [2]}]
One step at a time, you can approach it in the following manner.
loaded = [{6: [4, 1, 3]}, {1: [5]}, {10: [8, 6]}, {6: [7]}, {2: [2]}]
Items = {1: 1, 2: 2, 3: 2, 4: 2, 5: 2, 6: 3, 7: 4, 8: 5}
u_loaded = [{k: [Items[val] for val in v] for k,v in d.items()} for d in loaded]
For an Explanation of 1 liner, we can open it up:
u_loaded = [] #stores the list of dicts
for d in loaded:
u_d = {} #create empty result dict
for k,v in d.items():
u_d[k] = [Items[val] for val in v] #for every value, take the corresponding mapping result from loaded
u_loaded.append(u_d) #append the dictionary to the result list
Output:
[{6: [2, 1, 2]}, {1: [2]}, {10: [5, 3]}, {6: [4]}, {2: [2]}]
You can use a simple list comprehension:
result = [{k: [Items[v] for v in l] for k, l in d.items()} for d in loaded]
print(result)
Output:
[{6: [2, 1, 2]}, {1: [2]}, {10: [5, 3]}, {6: [4]}, {2: [2]}]
This is equivalent to the following for loop:
result = []
for d in loaded:
new_sub_dict = {}
for k, l in d.items():
new_sub_list = []
for v in l:
new_sub_list.append(Items[v])
new_sub_dict[k] = new_sub_list
result.append(new_sub_dict)
You may want to avoid loops in order to adopt a Pythonic style. What you would like to do can be achieved in just one line:
u_loaded = [{k: [Items[i] for i in v] for k, v in d.items()} for d in loaded]
It is using list comprehension to loop over all dictionaries in loaded. And then, it follows a loop over the dictionaries keys k and values v to reconstruct the dictionary you want to create.

Reading from file into dictionaries, and strange eval() behaviour

Creating dictionaries from file using eval(), or ast.literal_eval() (as suggested by others) yields strange results, and I'm not sure why.
My file, file.txt contains this:
{0 : {1: 6, 1:8}, 1 : {1:11}, 2 : {3: 9}, 3 : {},4 : {5:3},5 : {2: 7, 3:4}}
I read it into a dictionary and print the contents out as such
graph1 = {}
graph1 = ast.literal_eval(open("file.txt").read())
and I get this thing, where the {1:6} is missing.
{0: {1: 8}, 1: {1: 11}, 2: {3: 9}, 3: {}, 4: {5: 3}, 5: {2: 7, 3: 4}}
I change the contents of 'file.txt' to this:
{0: {2: 7, 3: 4}, 1: {1: 11}, 2: {3: 9}, 3: {}, 4: {5: 3}, 5: {2: 7, 3: 4}}
And then the correct contents display!
Then I change the contents of file.txt to this, where I rewrite 1:6 as 2:6
{0 : {2: 6, 1:8}, 1 : {1:11}, 2 : {3: 9}, 3 : {},4 : {5:3},5 : {2: 7, 3:4}}
And this is the output, where {2:6} and {1:8} switch places!
{0: {1: 8, 2: 6}, 1: {1: 11}, 2: {3: 9}, 3: {}, 4: {5: 3}, 5: {2: 7, 3: 4}}
All I want to do is correctly read the contents of a file into my dictionary. What is going wrong?
Dictionaries can not have duplicate key. In case same key is provided to the dict object, former value is overridden by the later value.
For example:
>>> d = {'a': 'x', 'b': 'y', 'c': 'z', 'a': 'w'}
>>> d
{'a': 'w', 'c': 'z', 'b': 'y'} # ('a': 'x') is overridden by ('a': 'w')
The reason of missing 1:6 is because of that you have 1:8 in your dictionary too, and since python use hash table for implementing the dictionaries, they don't preserve duplicate keys (because they have same hash value) and the reason of changing the order is that dictionaries don't have a specific order because of the way they are implemented.

Alternative to deepcopy in python

In a project we have to do for school, we got an assignment to write an implementation for the floyd-warshall algorithm.
One of the restrictions was, that we could not use import statements.
I had not read this and write my algorithm, using deepcopy. Now I am searching for a way to make my own sort of "copy" function.
The thing I want to copy is a dictionary of 2 dictionaries
{"a": {...}, "b": {...}}
Is this possible? thank you very much in advance
You can use a dict comprehension with copy method of dictionary :
d={"a": {...}, "b": {...}}
new={i:j.copy() for i,j in d.items()}
Demo :
>>> d ={1: {1: 5}, 2: {2: 2}, 3: {3: 9}}
>>> l ={i:j.copy() for i,j in d.items()}
>>> l[1][1]=0
>>> l
{1: {1: 0}, 2: {2: 2}, 3: {3: 9}}
>>> d
{1: {1: 5}, 2: {2: 2}, 3: {3: 9}}

Categories