point from a list into a dicitonary variable
Asked Answered
E

4

4

Assume you have a list

a = [3,4,1]

I want with this information to point to the dictionary:

b[3][4][1]

Now, what I need is a routine. After I see the value, to read and write a value inside b's position.

I don't like to copy the variable. I want to change variable b's content directly.

Engenia answered 10/8, 2012 at 15:53 Comment(2)
a, could GROW, I need a sollution, that independently of the lists size, it would successfully point the b element.Engenia
I was disappointed when b[*a] = 'foo' didn't know to unpack the arguments for dictionary traversal...Deadeye
H
12

Assuming b is a nested dictionary, you could do

reduce(dict.get, a, b)

to access b[3][4][1].

For more general object types, use

reduce(operator.getitem, a, b)

Writing the value is a bit more involved:

reduce(dict.get, a[:-1], b)[a[-1]] = new_value

All this assumes you don't now the number of elements in a in advance. If you do, you can go with neves' answer.

Hyperpituitarism answered 10/8, 2012 at 15:55 Comment(5)
+1 great answer, 245 reputation (up to now) on the first day is great to!Fredrika
something like this, the list "a" could grow. I need a function, where I give the variable "a" as argument, and I would point to b directly, and work straight a way, but not with a copy of it's variable.Engenia
@Engenia This solution is still fine if you just use itertools.islice: reduce(dict.get, islice(a, len(a) - 1), b)[a[-1]]Kleeman
@Engenia that dosn't make a copy if that's what you mean, otherwise this solution works for any number of elements in aKleeman
please post me a complete working example.\I didn't get it running.Engenia
P
2

This would be the basic algorithm:

To get the value of an item:

mylist = [3, 4, 1]
current = mydict
for item in mylist:
    current = current[item]
print(current)

To set the value of an item:

mylist = [3, 4, 1]
newvalue = "foo"

current = mydict
for item in mylist[:-1]:
    current = current[item]
current[mylist[-1]] = newvalue
Preserve answered 10/8, 2012 at 16:2 Comment(1)
when I would change current, mylist[item] is not changed.Engenia
G
1

Assuming the list length is fixed and already known

a = [3, 4, 1]
x, y, z = a
print b[x][y][z]

you can put this inside a function

Galvano answered 10/8, 2012 at 15:56 Comment(1)
Note that this assumes the number of elements in a is fixed. For a variable number of elements in a, you will need some kind of implicit or explicit loop.Hyperpituitarism
E
0

Let's write our own getnesteditem and setnesteditem:

def getnesteditem(xs, path):
    for i in path:
        xs = xs[i]
    return xs

def setnesteditem(xs, path, newvalue):
    for i in path[:-1]:
        xs = xs[i]
    xs[path[-1]] = newvalue

And try it with your list of indices a = [3,4,1]:

a = [3, 4, 1]
b = [[[15*i+3*j+k for k in range(3)] for j in range(5)] for i in range(4)]
print(*b, sep='\n')
# [[ 0,  1,  2], [ 3,  4,  5], [ 6,  7,  8], [ 9, 10, 11], [12, 13, 14]]
# [[15, 16, 17], [18, 19, 20], [21, 22, 23], [24, 25, 26], [27, 28, 29]]
# [[30, 31, 32], [33, 34, 35], [36, 37, 38], [39, 40, 41], [42, 43, 44]]
# [[45, 46, 47], [48, 49, 50], [51, 52, 53], [54, 55, 56], [57, 58, 59]]

print(getnesteditem(b, a))
# 58

setnesteditem(b, a, -9)
print(*b, sep='\n')
# [[ 0,  1,  2], [ 3,  4,  5], [ 6,  7,  8], [ 9, 10, 11], [12, 13, 14]]
# [[15, 16, 17], [18, 19, 20], [21, 22, 23], [24, 25, 26], [27, 28, 29]]
# [[30, 31, 32], [33, 34, 35], [36, 37, 38], [39, 40, 41], [42, 43, 44]]
# [[45, 46, 47], [48, 49, 50], [51, 52, 53], [54, 55, 56], [57, -9, 59]]
Exception answered 19/12, 2023 at 10:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.