Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #69549 > unrolled thread

Retrieve item deep in dict tree?

Started byRoy Smith <roy@panix.com>
First post2014-04-02 13:58 -0400
Last post2014-04-03 01:00 -0600
Articles 8 — 6 participants

Back to article view | Back to comp.lang.python


Contents

  Retrieve item deep in dict tree? Roy Smith <roy@panix.com> - 2014-04-02 13:58 -0400
    Re: Retrieve item deep in dict tree? John Gordon <gordon@panix.com> - 2014-04-02 18:03 +0000
    Re: Retrieve item deep in dict tree? Steven D'Aprano <steve@pearwood.info> - 2014-04-02 20:18 +0000
      Re: Retrieve item deep in dict tree? Ethan Furman <ethan@stoneleaf.us> - 2014-04-02 13:25 -0700
    Re: Retrieve item deep in dict tree? Rustom Mody <rustompmody@gmail.com> - 2014-04-02 19:41 -0700
      Re: Retrieve item deep in dict tree? Rustom Mody <rustompmody@gmail.com> - 2014-04-02 21:15 -0700
        Re: Retrieve item deep in dict tree? Steven D'Aprano <steve@pearwood.info> - 2014-04-03 05:29 +0000
        Re: Retrieve item deep in dict tree? Ian Kelly <ian.g.kelly@gmail.com> - 2014-04-03 01:00 -0600

#69549 — Retrieve item deep in dict tree?

FromRoy Smith <roy@panix.com>
Date2014-04-02 13:58 -0400
SubjectRetrieve item deep in dict tree?
Message-ID<mailman.8818.1396461529.18130.python-list@python.org>
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.

---
Roy Smith
roy@panix.com

[toc] | [next] | [standalone]


#69550

FromJohn Gordon <gordon@panix.com>
Date2014-04-02 18:03 +0000
Message-ID<lhhjcr$e5s$1@reader1.panix.com>
In reply to#69549
In <mailman.8818.1396461529.18130.python-list@python.org> Roy Smith <roy@panix.com> writes:

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

-- 
John Gordon         Imagine what it must be like for a real medical doctor to
gordon@panix.com    watch 'House', or a real serial killer to watch 'Dexter'.

[toc] | [prev] | [next] | [standalone]


#69554

FromSteven D'Aprano <steve@pearwood.info>
Date2014-04-02 20:18 +0000
Message-ID<533c70a5$0$2909$c3e8da3$76491128@news.astraweb.com>
In reply to#69549
On Wed, 02 Apr 2014 13:58:16 -0400, Roy Smith wrote:

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


-- 
Steven

[toc] | [prev] | [next] | [standalone]


#69555

FromEthan Furman <ethan@stoneleaf.us>
Date2014-04-02 13:25 -0700
Message-ID<mailman.8821.1396471817.18130.python-list@python.org>
In reply to#69554
On 04/02/2014 01:18 PM, Steven D'Aprano wrote:
> On Wed, 02 Apr 2014 13:58:16 -0400, Roy Smith wrote:
>
>> 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.  :)

--
~Ethan~

[toc] | [prev] | [next] | [standalone]


#69566

FromRustom Mody <rustompmody@gmail.com>
Date2014-04-02 19:41 -0700
Message-ID<5d184a3a-c8d2-40d6-8055-7f7d1eb96127@googlegroups.com>
In reply to#69549
On Wednesday, April 2, 2014 11:28:16 PM UTC+5:30, Roy Smith wrote:
> 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
>>> nested = {'a':{'b':{'c':"Hiii!!"}}}

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][b][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

[toc] | [prev] | [next] | [standalone]


#69568

FromRustom Mody <rustompmody@gmail.com>
Date2014-04-02 21:15 -0700
Message-ID<141eca25-744b-47c0-8b2b-d8d08f8b27ef@googlegroups.com>
In reply to#69566
On Thursday, April 3, 2014 8:11:33 AM UTC+5:30, Rustom Mody wrote:
> On Wednesday, April 2, 2014 11:28:16 PM UTC+5:30, Roy Smith wrote:
> > 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!!'

[toc] | [prev] | [next] | [standalone]


#69569

FromSteven D'Aprano <steve@pearwood.info>
Date2014-04-03 05:29 +0000
Message-ID<533cf1cb$0$2909$c3e8da3$76491128@news.astraweb.com>
In reply to#69568
On Wed, 02 Apr 2014 21:15:23 -0700, Rustom Mody wrote:

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


Nice!



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#69571

FromIan Kelly <ian.g.kelly@gmail.com>
Date2014-04-03 01:00 -0600
Message-ID<mailman.8827.1396508455.18130.python-list@python.org>
In reply to#69568
On Wed, Apr 2, 2014 at 10:15 PM, Rustom Mody <rustompmody@gmail.com> wrote:
> On Thursday, April 3, 2014 8:11:33 AM UTC+5:30, Rustom Mody wrote:
>> On Wednesday, April 2, 2014 11:28:16 PM UTC+5:30, Roy Smith wrote:
>> > 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)

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web