Map a dictionary on a list of dictionaries - python

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.

Related

python: use sorted() function for dict inside the dict

this is the dict I got now:
dict1 = {1: {7: [6], 1: [7]}, 2: {3: [1, 6], 2: [2, 7, 5]}}
And I would like to order subdictionary by keys:
dict2 = {1: {1: [7], 7: [6]}, 2: {2: [2, 7, 5], 3: [1, 6]}}
I tried some methods, but it didn't work...Like this one. Please help me.
print(sorted(dict1.items(), key=lambda x: x[1][1]))
As long as you use sufficiently high version of Python3 you can do:
dict1 = {1: {7: [6], 1: [7]}, 2: {3: [1, 6], 2: [2, 7, 5]}}
dict2 = {k: dict(sorted(v.items())) for k, v in dict1.items()}
print(dict2)
Prints:
{1: {1: [7], 7: [6]}, 2: {2: [2, 7, 5], 3: [1, 6]}}

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]}}

Python - How can I extract all the shortest path from this networkx Code?

I tried running this and I'm getting shortest path with memory address.How can I remove the memory address from the output
import networkx as nx
G=nx.Graph()
G.add_nodes_from([1,2,3,4])
G.add_weighted_edges_from([(1,2,8),(1,3,5),(2,4,1),(3,4,2)])
print(nx.floyd_warshall(G))
Here's the output
{1: defaultdict(<function floyd_warshall_predecessor_and_distance.<locals>.<lambda>.<locals>.<lambda> at 0x000002AA0C397B70>, {1: 0, 2: 8, 3: 5, 4: 7}),
`2: defaultdict(<function floyd_warshall_predecessor_and_distance.<locals>.<lambda>.<locals>.<lambda> at 0x000002AA0D96A378>, {1: 8, 2: 0, 3: 3, 4: 1}),
3: defaultdict(<function floyd_warshall_predecessor_and_distance.<locals>.<lambda>.<locals>.<lambda> at 0x000002425C098F28>, {1: 5, 2: 3, 3: 0, 4: 2}),
4: defaultdict(<function floyd_warshall_predecessor_and_distance.<locals>.<lambda>.<locals>.<lambda> at 0x000002425C0A2048>, {1: 7, 2: 1, 3: 2, 4: 0})}
The output that I want is something like this-
1:{1:0, 2:8, 3:5, 4:7}
2:{1:8, 2:0, 3:3, 4:1}
3:{1:5, 2:3, 3:0, 4:2}
4:{1:7, 2:1, 3:2, 4:0}
Looks like it's a dictionary inside a dictionary:
You can do something like this:
data = nx.floyd_warshall(G)
for key, value in data.iteritems():
print('%s %s' % (key, value.values()))
Or if you want the key:value pair:
import json
data = nx.floyd_warshall(G)
for key, value in data.iteritems():
print('%s %s' % (key, json.dumps(value)))
It's printing out a dict of defaultdicts (which is what networkx returns), but you want it to print a dict of dicts, so you need to convert those defaultdicts into dicts.
X = nx.floyd_warshall(G)
Y = {a:dict(b) for a,b in X.items()}
print(Y)
> {1: {1: 0, 2: 8, 3: 5, 4: 7},
2: {1: 8, 2: 0, 3: 3, 4: 1},
3: {1: 5, 2: 3, 3: 0, 4: 2},
4: {1: 7, 2: 1, 3: 2, 4: 0}}

Converting list of lists of lists into dictionary of dictionaries (Python)

Suppose I have a list X = [[[2, 2]], [[2, 5], [3, 1]], [[3, 3], [4, 4], [1, 6]], [[1, 1], [4, 0]], [[]]]. I want to convert X into a dictionary of dictionaries like so.
G = {0: {2: 2},
1: {2: 5, 3: 1},
2: {3: 3, 4: 4, 1: 6},
3: {1: 1, 4: 0},
4: {}
}
So far I have
for i in range(0,len(X)):
for j in range(0, len(X[i])):
G[i] = {X[i][j][0]: X[i][j][1]}
which produces
{0: {2: 2}}
{0: {2: 2}, 1: {2: 5}}
{0: {2: 2}, 1: {3: 1}}
{0: {2: 2}, 1: {3: 1}, 2: {3: 3}}
{0: {2: 2}, 1: {3: 1}, 2: {4: 4}}
{0: {2: 2}, 1: {3: 1}, 2: {1: 6}}
{0: {2: 2}, 1: {3: 1}, 2: {1: 6}, 3: {1: 1}}
{0: {2: 2}, 1: {3: 1}, 2: {1: 6}, 3: {4: 0}}
Traceback (most recent call last):
G[i] = {X[i][j][0]: X[i][j][1]}
IndexError: list index out of range
First it only updates the dictionaries instead of appending new keys, second it fails me at my empty list.
Any suggestions?
If you're using Python 2.7 you can use a dictionary comprehension.
X = [[[2, 2]], [[2, 5], [3, 1]], [[3, 3], [4, 4], [1, 6]], [[1, 1], [4, 0]], [[]]]
d = {k: dict(v) if v[0] else {} for k, v in enumerate(X)}
someone had a nice answer but they deleted it where they also used a dictionary comprehension but handled the empty lists better (I think). It went like so
d = {k: dict(item for item in v if item) for k, v in enumerate(X)}
Your assignment to G should be:
G[i][X[i][j][0]] = X[i][j][1]
And you'll need to initialize each item of G before the inner loop:
G[i] = {}

Dictionary comprehension with conditional

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)

Categories