Convert a list of tuples to a dictionary - python

I have a list of tuples with three elements:
A = [[(72, 1, 2), (96, 1, 4)],
[(72, 2, 1), (80, 2, 4)],
[],
[(96, 4, 1), (80, 4, 2), (70, 4, 5)],
[(70, 5, 4)],
]
I need to convert it to a dictionary in this format (note that the second element in the tuple will be the key):
A_dict = { 1: {2:72, 4:96},
2: {1:72, 4:80},
3: {},
4: {1:96, 2:80, 5:70},
5: {4:70},
}
Is there a way to convert A to A_dict?
I tried this:
A_dict = {b:{a:c} for a,b,c in A}
but I got an error:
ValueError: not enough values to unpack (expected 3, got 2)

You can just do:
A_dict = {k+1: {t[2]: t[0] for t in l} for k, l in enumerate(A)}
>>> A_dict
{
1: {2: 72, 4: 96},
2: {1: 72, 4: 80},
3: {},
4: {1: 96, 2: 80, 5: 70},
5: {4: 70}
}

By iterating on the indices of the list, according to its length. And for each value building its own dictionary:
A_dict = {i + 1 : {v[2] : v[0] for v in A[i]} for i in range(len(A))}
will output:
{1: {2: 72, 4: 96},
2: {1: 72, 4: 80},
3: {},
4: {1: 96, 2: 80, 5: 70},
5: {4: 70}}
Actually your desired code is:
A_dict = {A[i][0][1] : {v[2] : v[0] for v in A[i]} for i in range(len(A)) if len(A[i]) > 0}
But that will 'skip' the third line, as there is no list, thus not able to determinate the actual key, according to your specification.

Related

In Python: In a list of tuples that represent X, Y points, what is the syntax to access a particular X or Y?

For example if
list = [{0: 1}, {0: 2}, {1: 0}, {1: 2}, {2: 0}, {2: 1}, {2: 2}]
what is the syntax to get the x and y of the second item?
x = list[1] ?
y = list[1] ?
The list you have shown is:
[{0: 1}, {0: 2}, {1: 0}, {1: 2}, {2: 0}, {2: 1}, {2: 2}]
This is a list of dicts, each with a single element. For the second item (at index 1), the dictionary has one key/value pair with key 0 and value 2. To access this, you could do this:
myList = [{0: 1}, {0: 2}, {1: 0}, {1: 2}, {2: 0}, {2: 1}, {2: 2}]
myDict = myList[1]
key, value = next(iter(myDict.items()))
print(key, value)
If what you want instead is a list of tuples, that would be something like:
[(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1), (2, 2)]
You could access the second tuple in the list as follows:
myList = [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1), (2, 2)]
x = myList[1][0]
y = myList[1][1]
print(x, y)
Alternatively, you could use this more concise assignment syntax:
x, y = myList[1]

How to get and modify the value of nested dictionary?

I have this kind of dictionary in python:
x = {'test': {1: 2, 2: 4, 3: 5},
'this': {1: 2, 2: 3, 7: 6},
'is': {1: 2},
'something': {90: 2,92:3}}
I want to modify all of the value in the key by whatever value I want. Let's say 100, the methods I tried are below:
counter = 1
print(x)
for key,anotherKey in x.items():
while counter not in x[key]:
counter+=1
while counter in x[key]:
x[key][counter] = 100
counter+=1
counter =0
Which got the result below:
{'test': {1: 100, 2: 100, 3: 100},
'this': {1: 100, 2: 100, 7: 6},
'is': {1: 100},
'something': {90: 100,92: 3}}
I know why this is happening it's because the loop doesn't consider if the differences is more than 1 which in this case in 'this' : where the differences from 2 to 7 is more than 1. However I don't know how to solve this.
You can iterate via a nested for loop:
x = {'test': {1: 2, 2: 4, 3: 5},
'this': {1: 2, 2: 3, 7: 6},
'is': {1: 2},
'something': {90: 2,92:3}}
for a in x:
for b in x[a]:
x[a][b] = 100
print(x)
{'is': {1: 100},
'something': {90: 100, 92: 100},
'test': {1: 100, 2: 100, 3: 100},
'this': {1: 100, 2: 100, 7: 100}}
Or for a new dictionary you can use a dictionary comprehension:
res = {a: {b: 100 for b in x[a]} for a in x}
You can use dictionary comprehension in this way:
{a: {b:100 for b in d} for (a,d) in x.items()}

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

Hard copying dicts in a list

When I try the following list creation, I see that each element refers to a different object.
>>> a = [1] * 7
>>> a[0] = 2
>>> a
Out[17]: [2, 1, 1, 1, 1, 1, 1]
However, when I try the following list creation with dictionaries, I see that each element refers to the same object.
a = [{1:10, 2:20}] * 7
a[0][1] = 30
a
Out[20]:
[{1: 30, 2: 20},
{1: 30, 2: 20},
{1: 30, 2: 20},
{1: 30, 2: 20},
{1: 30, 2: 20},
{1: 30, 2: 20},
{1: 30, 2: 20}]
How can I create this second list as easy as possible, but with the elements copies instead of references?
>>> a = [{1:10, 2:20} for _ in range(7)]
>>> a[0][1] = 30
>>> a
[{1: 30, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}]
Actually when you create a list with multiplication python will creating a list with repeated items with same memory address :
>>> a=[1]*7
>>> id(a[0])
40968536
>>> id(a[1])
40968536
>>> a = [{1:10, 2:20}]*7
>>> id(a[0])
140379402804592
>>> id(a[1])
140379402804592
But when you want to change an immutable object like (numbers,tuple,string,...) python will change the reference not the object!
And when you change a mutable object python will change the object itself,so all the entries will change.
So as a more efficient way in python 2 you can use xrange (xrange return a generator instead a list) (in 3 range ) within a list comprehension to create your list :
>>> a = [{1:10, 2:20} for _ in xrange(7)]
>>> a
[{1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}]
>>> a[0][1]=0
>>> a
[{1: 0, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}]
>>> id(a[0])
140379402734400
>>> id(a[1])
140379402809424

Sorting a dictionary of dictionary using values in Python

How Do I sort a dict of dict in python??
I have a dictionary :
d = {
1: {2: 30, 3: 40, 4: 20, 6: 10},
2: {3: 30, 4: 60, 5: -60},
3: {1: -20, 5: 60, 6: 100},
}
How can I get the sorted (reverse) dict based on their values ?? How can I get the output like:
d = {
1: {3: 40, 2: 30, 4: 20, 6: 10},
2: {4: 60, 3: 30, 5: -60},
3: { 6: 100, 5: 60,1: -20},
}
What Padraic did, more compacted:
sort_vals = lambda d: OrderedDict(sorted(d.items(), key=lambda pair: pair[1], reversed=True))
d = dict((k, sort_vals(sub_dict)) for k, sub_dict in d.items())
(Not tested)
If you want order you need an OrderedDict of OrderedDicts, by chance the outer dict is in sorted order but normal dicts have no order:
from collections import OrderedDict
d = {
1: {2: 30, 3: 40, 4: 20, 6: 10},
2: {3: 30, 4: 60, 5: -60},
3: {1: -20, 5: 60, 6: 100},
}
keys = sorted(d.keys()) # sort outer dict keys
o = OrderedDict()
for k in keys: # loop over the sorted keys
# make an orderedDict out of the sorted items from each sub dict.
o[k] = OrderedDict((k,v) for k,v in sorted(d[k].items(),key=lambda x:x[1],reverse=True))
print(o)
OrderedDict([(1, OrderedDict([(3, 40), (2, 30), (4, 20), (6, 10)])), (2, OrderedDict([(4, 60), (3, 30), (5, -60)])), (3, OrderedDict([(6, 100), (5, 60), (1, -20)]))])

Categories