Retrieve item deep in dict tree?


R

Roy Smith

I have a big hairy data structure which is a tree of nested dicts. I have a sequence of strings which represents a path through the tree. Different leaves in the tree will be at different depths (which range from 1 to about 4 or 5 at most). I want to get the value stored at that path. Thus, if

keys = ['foo', 'bar', 'baz']

I want to retrieve tree['foo']['bar']['baz'].

Is there some idiomatic, non-cryptic way to write that as a one-liner?

I'm using Python 2.7.
 
Ad

Advertisements

J

John Gordon

In said:
I have a big hairy data structure which is a tree of nested dicts. I =
have a sequence of strings which represents a path through the tree. =
Different leaves in the tree will be at different depths (which range =
from 1 to about 4 or 5 at most). I want to get the value stored at that =
path. Thus, if
keys =3D ['foo', 'bar', 'baz']
I want to retrieve tree['foo']['bar']['baz'].
Is there some idiomatic, non-cryptic way to write that as a one-liner?
I'm using Python 2.7.

How about three lines?

subtree = tree
for key in keys:
subtree = subtree.get(key)
 
S

Steven D'Aprano

I have a big hairy data structure which is a tree of nested dicts. I
have a sequence of strings which represents a path through the tree.
Different leaves in the tree will be at different depths (which range
from 1 to about 4 or 5 at most). I want to get the value stored at that
path. Thus, if

keys = ['foo', 'bar', 'baz']

I want to retrieve tree['foo']['bar']['baz'].

Is there some idiomatic, non-cryptic way to write that as a one-liner?

Er, idiomatic one liner? No, not really. But a helper function makes
nearly anything into a one-liner:

def traverse(tree, *keys):
t = tree
for k in keys:
t = t[k]
return t

# one-liner
leaf = traverse(tree, *list_of_keys)
 
E

Ethan Furman

I have a big hairy data structure which is a tree of nested dicts. I
have a sequence of strings which represents a path through the tree.
Different leaves in the tree will be at different depths (which range
from 1 to about 4 or 5 at most). I want to get the value stored at that
path. Thus, if

keys = ['foo', 'bar', 'baz']

I want to retrieve tree['foo']['bar']['baz'].

Is there some idiomatic, non-cryptic way to write that as a one-liner?

Er, idiomatic one liner? No, not really. But a helper function makes
nearly anything into a one-liner:

def traverse(tree, *keys):
t = tree
for k in keys:
t = t[k]
return t

# one-liner
leaf = traverse(tree, *list_of_keys)

+1

Short, simple -- good Python. :)
 
R

Rustom Mody

I have a big hairy data structure which is a tree of nested dicts. I have a sequence of strings which represents a path through the tree. Different leaves in the tree will be at different depths (which range from 1 to about 4 or 5 at most). I want to get the value stored at that path. Thus, if
keys = ['foo', 'bar', 'baz']
I want to retrieve tree['foo']['bar']['baz'].
Is there some idiomatic, non-cryptic way to write that as a one-liner?
I'm using Python 2.7.

What you are asking for is probably:
reduce((lambda tr, att: tr[att]), ['a','b','c'], nested) 'Hiii!!'

I used a nested thus
But what you are REALLY looking for is what Steven/Gordon gave <wink>

In order to see more visibly that those whiles are just reduces
you may want to rewrite as:
reduce((lambda tr, att: str(tr) + "[" + str(att) + "]"), ['a','b','c'],"nested")
'nested[a][c]'

IOW the 'theorem' I am using is that

reduce(op, id, l)

is short for

while l:
id, l = op(id, l[0]), l[1:]
return id
 
R

Rustom Mody

I have a big hairy data structure which is a tree of nested dicts. I have a sequence of strings which represents a path through the tree. Different leaves in the tree will be at different depths (which range from 1 to about 4 or 5 at most). I want to get the value stored at that path. Thus, if
keys = ['foo', 'bar', 'baz']
I want to retrieve tree['foo']['bar']['baz'].
Is there some idiomatic, non-cryptic way to write that as a one-liner?
I'm using Python 2.7.
What you are asking for is probably:
reduce((lambda tr, att: tr[att]), ['a','b','c'], nested)
'Hiii!!'

Shorter version:
reduce(dict.get, ['a','b','c'], nested)
'Hiii!!'
 
Ad

Advertisements

Ad

Advertisements

I

Ian Kelly

I have a big hairy data structure which is a tree of nested dicts. I have a sequence of strings which represents a path through the tree. Different leaves in the tree will be at different depths (which range from 1 to about 4 or 5 at most). I want to get the value stored at that path. Thus,if
keys = ['foo', 'bar', 'baz']
I want to retrieve tree['foo']['bar']['baz'].
Is there some idiomatic, non-cryptic way to write that as a one-liner?
I'm using Python 2.7.
What you are asking for is probably:
reduce((lambda tr, att: tr[att]), ['a','b','c'], nested)
'Hiii!!'

Shorter version:
reduce(dict.get, ['a','b','c'], nested)
'Hiii!!'

That breaks if the dicts are ever replaced with an alternate mapping
implementation (or a dict subclass that overrides the get method), and
incorrectly returns None instead of raising KeyError if the last key
in the sequence does not exist (and if any of the other keys don't
exist, you'll get a TypeError instead of a KeyError). This is more
robust:

import operator
reduce(operator.getitem, ['a', 'b', 'c'], nested)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top