How to get and modify the value of nested dictionary? - python

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

Related

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

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.

How do I find out if a integer variable in python has an out of scope hidden value?

in the code here
How do I force static methods to use local not global variables in Python?
i have a variable that is being passed between methods besides the one in the question. the variable is current_line
def line_tocsv(csv_dict={}, line={}, current_line=0):
csv_line, current_line = LineHandler.create_csv(current_line, kline)
if current_line in csv_dict:
csv_dict[current_line].update(csv_line)
else:
csv_dict[current_line] = csv_line
return csv_dict
when this code is run, it produced an output simmilar to this
>>> a={0:{"aa":1,"bb":"wasd"},1:{"aa":1,"bb":"wasd"}}
>>> a
{0: {'aa': 1, 'bb': 'wasd'}, 1: {'aa': 1, 'bb': 'wasd'}}
>>> a[1].update({"cc":"foo"})
>>> a
{0: {'aa': 1, 'cc': 'foo' 'bb': 'wasd'}, 1: {'aa': 1, 'cc': 'foo', 'bb': 'wasd'}}
how do i make it so that the csv_line dict is only entered into ONE sub dict?!
changing the variable names does not work and i suspect it is because only the references are passed between functions, but i dont know enough python to know where those references actually go and what their order of ops etc is
First, don't use mutable default arguments
def line_tocsv(csv_dict=None, ....):
if not csv_dict:
csv_dict = {}
....
Next, use copy of dict, not pointer:
csv_dict[current_line] = csv_line.copy()
EDIT:
Try to do this:
>>> a
{1: 2, 3: 4}
>>> b = {1:a,2:a}
>>> b
{1: {1: 2, 3: 4}, 2: {1: 2, 3: 4}}
>>> b[1][7] = 8
>>> b
{1: {1: 2, 3: 4, 7: 8}, 2: {1: 2, 3: 4, 7: 8}}
If you want to use value of dict instead of pointer:
>>> a
{1: 2, 3: 4}
>>> b = {1:a.copy(),2:a.copy()}
>>> b
{1: {1: 2, 3: 4}, 2: {1: 2, 3: 4}}
>>> b[1][7] = 8
>>> b
{1: {1: 2, 3: 4, 7: 8}, 2: {1: 2, 3: 4}}

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

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

Categories