user2159982
user2159982

Reputation: 23

Appending a value to python dictionary value using the key if the value is a multiple array

I declared a python dictionary with key and value as multiple array. Is it possible to append an array using the key and value index?

This is the way I initialized the python dictionary cvfoldacc

a = []
b = [] 
c = [] 
d = [] 
e = [] 
f = []
classifiers = [a,b,c,d,e,f]
cvfoldacc = dict.fromkeys(range(2,11), classifiers) 

And the result of this initialization is as follows:

cvfoldacc>>

{2: [[], [], [], [], [], []],
 3: [[], [], [], [], [], []],
 4: [[], [], [], [], [], []],
 5: [[], [], [], [], [], []],
 6: [[], [], [], [], [], []],
 7: [[], [], [], [], [], []],
 8: [[], [], [], [], [], []],
 9: [[], [], [], [], [], []],
 10: [[], [], [], [], [], []]}

When I tried to append the first list of key(2) with the code cvfoldacc[2][0].append(8), I am getting the result as:

{2: [[8], [], [], [], [], []],
 3: [[8], [], [], [], [], []],
 4: [[8], [], [], [], [], []],
 5: [[8], [], [], [], [], []],
 6: [[8], [], [], [], [], []],
 7: [[8], [], [], [], [], []],
 8: [[8], [], [], [], [], []],
 9: [[8], [], [], [], [], []],
 10: [[8], [], [], [], [], []]}

But the expected answer should be this:

{2: [[8], [], [], [], [], []],
 3: [[], [], [], [], [], []],
 4: [[], [], [], [], [], []],
 5: [[], [], [], [], [], []],
 6: [[], [], [], [], [], []],
 7: [[], [], [], [], [], []],
 8: [[], [], [], [], [], []],
 9: [[], [], [], [], [], []],
 10: [[], [], [], [], [], []]}

Upvotes: 0

Views: 61

Answers (2)

han solo
han solo

Reputation: 6590

You need to create new lists for values of each key like,

>>> a = []
>>> b = [] 
>>> c = [] 
>>> d = [] 
>>> e = [] 
>>> f = []
>>> classifiers = [a,b,c,d,e,f] 
>>> 
>>> d = {k:[x[:] for x in classifiers] for k in range(2,11)} # note i am creating a copy using the `list[:]` notation.
# either the comprehension or `k: copy.deepcopy(classifiers)` is fine
>>> d
{2: [[], [], [], [], [], []], 3: [[], [], [], [], [], []], 4: [[], [], [], [], [], []], 5: [[], [], [], [], [], []], 6: [[], [], [], [], [], []], 7: [[], [], [], [], [], []], 8: [[], [], [], [], [], []], 9: [[], [], [], [], [], []], 10: [[], [], [], [], [], []]}
>>> d[2][0].append(1)
>>> d
{2: [[1], [], [], [], [], []], 3: [[], [], [], [], [], []], 4: [[], [], [], [], [], []], 5: [[], [], [], [], [], []], 6: [[], [], [], [], [], []], 7: [[], [], [], [], [], []], 8: [[], [], [], [], [], []], 9: [[], [], [], [], [], []], 10: [[], [], [], [], [], []]}

Upvotes: 1

Sayandip Dutta
Sayandip Dutta

Reputation: 15872

This is the same old deep copy vs shallow copy thing. Try this:

>>> a = []
>>> b = [] 
>>> c = [] 
>>> d = [] 
>>> e = [] 
>>> f = []
>>> classifiers = [a,b,c,d,e,f]
>>> import copy
>>> cvfoldacc = {k:copy.deepcopy(classifiers) for k in range(2,11)}
>>> cvfoldacc[2][0].append(8)
>>> cvfoldacc 
{2: [[8], [], [], [], [], []],
 3: [[], [], [], [], [], []],
 4: [[], [], [], [], [], []],
 5: [[], [], [], [], [], []],
 6: [[], [], [], [], [], []],
 7: [[], [], [], [], [], []],
 8: [[], [], [], [], [], []],
 9: [[], [], [], [], [], []],
 10: [[], [], [], [], [], []]}

You were doing:

a = []
b = [] 
c = [] 
d = [] 
e = [] 
f = []
classifiers = [a,b,c,d,e,f]
cvfoldacc = dict.fromkeys(range(2,11), classifiers) 

Now, the dictionary that is getting created, has the same list in every key, not only they look same, those are the exact same objects, having same identity (memory location in CPython). Let's see:

>>> id(cvfoldacc[2])
171760008
>>> id(cvfoldacc[3])
171760008

And these will be same for other values as well. So dict.fromkeys() assigns the same value to all the keys in the dictionary, does not create a copy of it.

Now, another way, where you make a shallow copy, and this issue would be solved:

>>> cvfoldacc = {a:classifiers.copy() for a in range(2,11)}
>>> id(cvfoldacc[2])
171840616
>>> id(cvfoldacc[3])
171847688

Solved right?

>>> cvfoldacc[2][0].append(8)
{2: [[8], [], [], [], [], []],
 3: [[8], [], [], [], [], []],
 4: [[8], [], [], [], [], []],
 5: [[8], [], [], [], [], []],
 6: [[8], [], [], [], [], []],
 7: [[8], [], [], [], [], []],
 8: [[8], [], [], [], [], []],
 9: [[8], [], [], [], [], []],
 10: [[8], [], [], [], [], []]}

Apparently not!! Let's now look DEEPER. Let's look at the ids of the lists inside the lists:

>>> id(cvfoldacc[2][0])
171810120
>>> id(cvfoldacc[3][0])
171810120

So even though list.copy() created a copy of the outerlist, the inner lists are the same. So essentially you are appending in list: a which is present in all the keys so everything is getting modified.

Deepcopy copied all the objects recursively, avoiding the issue.

Upvotes: 2

Related Questions