how to safely extract dict values

Discussion in 'Python' started by David Zaret, Jul 31, 2006.

  1. David Zaret

    David Zaret Guest

    i have a dict with a particular key - the values for this key will be
    None, one valid scalar, or a list:

    {mykey, None}
    {mykey, "foo"}
    {mykey, ["bar", "baz"]}

    let's ignore the None case - in the case of the one or many values, i
    want to suck the values into a list. here's one way to do this:

    if mydict.has_key(mykey):
    vals=[]
    _v = mydict[mykey]
    if isinstance(_v, types.ListType):
    vals.extend(_v)
    else:
    vals.append(_v)
    # now we can safely iterate through acts
    for val in vals:
    .....


    my way is ugly. what's a better way?

    thanks,

    ---- dz
     
    David Zaret, Jul 31, 2006
    #1
    1. Advertising

  2. David Zaret

    Paul Rubin Guest

    David Zaret <> writes:
    > my way is ugly. what's a better way?


    Untested:

    for key in mydict:
    if isinstance(mydict[key], list):
    vals.extend(mydict[key])
    else:
    vals.append(mydict[key])
     
    Paul Rubin, Jul 31, 2006
    #2
    1. Advertising

  3. Paul Rubin wrote:
    > David Zaret <> writes:
    >> my way is ugly. what's a better way?

    >
    > Untested:
    >
    > for key in mydict:
    > if isinstance(mydict[key], list):
    > vals.extend(mydict[key])
    > else:
    > vals.append(mydict[key])


    Too much useless lookup IMHO...

    vals = []
    for k, v in mydict.items():
    if isinstance(v, list):
    vals.extend(v)
    else:
    vals.append(v)

    !-)

    But this is not that different from what the OP found so ugly...

    --
    bruno desthuilliers
    python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
    p in ''.split('@')])"
     
    Bruno Desthuilliers, Jul 31, 2006
    #3
  4. David Zaret

    Amit Khemka Guest

    On 7/31/06, David Zaret <> wrote:
    > i have a dict with a particular key - the values for this key will be
    > None, one valid scalar, or a list:
    >
    > {mykey, None}
    > {mykey, "foo"}
    > {mykey, ["bar", "baz"]}
    >
    > let's ignore the None case - in the case of the one or many values, i
    > want to suck the values into a list. here's one way to do this:
    >
    > if mydict.has_key(mykey):
    > vals=[]
    > _v = mydict[mykey]
    > if isinstance(_v, types.ListType):
    > vals.extend(_v)
    > else:
    > vals.append(_v)
    > # now we can safely iterate through acts
    > for val in vals:
    > .....


    how about:

    vals = []
    for val in mydict.values():
    try: vals.extend(val)
    except: vals.append(val)

    cheers,
    amit.



    --
    ----
    Amit Khemka -- onyomo.com
    Home Page: www.cse.iitd.ernet.in/~csd00377
    Endless the world's turn, endless the sun's Spinning, Endless the quest;
    I turn again, back to my own beginning, And here, find rest.
     
    Amit Khemka, Jul 31, 2006
    #4
  5. David Zaret wrote:
    > i have a dict with a particular key - the values for this key will be
    > None, one valid scalar, or a list:
    >
    > {mykey, None}
    > {mykey, "foo"}
    > {mykey, ["bar", "baz"]}
    >
    > let's ignore the None case - in the case of the one or many values, i
    > want to suck the values into a list. here's one way to do this:
    >
    > if mydict.has_key(mykey):
    > vals=[]
    > _v = mydict[mykey]
    > if isinstance(_v, types.ListType):
    > vals.extend(_v)
    > else:
    > vals.append(_v)
    > # now we can safely iterate through acts
    > for val in vals:
    > .....
    >
    >
    > my way is ugly. what's a better way?


    If you have control over the dict's creation and 'filling', you may want
    to handle the case there - eventually using a custom dict-like object
    that stores everything (but None) in lists. The implementation code for
    this object will not be less ugly than the one above, but at least
    ugliness will be hidden away !-)

    Else, you can shorten the code a bit (NB : ignoring the 'None' case...):

    v = d[k]
    v = ([v], v)[isinstance(v, list)]

    And this can be hidden away in a function:

    def get_as_list(d, k):
    v = d[k]
    return ([v], v)[isinstance(v, list)]

    vals = get_as_list(mydict, mykey)


    I don't like using isinstance() tests too much, but it depends on the
    context...

    HTH

    --
    bruno desthuilliers
    python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
    p in ''.split('@')])"
     
    Bruno Desthuilliers, Jul 31, 2006
    #5
  6. David Zaret

    Paul Rubin Guest

    Bruno Desthuilliers <> writes:
    > Too much useless lookup IMHO...


    Actually, you, me, and Amit all mis-read David's original exapmle.
    What he really wanted was (let's see if I get it right this time):

    if mykey in mydict:
    v = mydict[mykey]
    if not isinstance(v, list):
    v = [v]
    for val in v: ...
     
    Paul Rubin, Jul 31, 2006
    #6
  7. Amit Khemka wrote:
    > On 7/31/06, David Zaret <> wrote:
    >> i have a dict with a particular key - the values for this key will be
    >> None, one valid scalar, or a list:
    >>
    >> {mykey, None}
    >> {mykey, "foo"}
    >> {mykey, ["bar", "baz"]}
    >>
    >> let's ignore the None case - in the case of the one or many values, i
    >> want to suck the values into a list. here's one way to do this:
    >>
    >> if mydict.has_key(mykey):
    >> vals=[]
    >> _v = mydict[mykey]
    >> if isinstance(_v, types.ListType):
    >> vals.extend(_v)
    >> else:
    >> vals.append(_v)
    >> # now we can safely iterate through acts
    >> for val in vals:
    >> .....

    >
    > how about:
    >
    > vals = []
    > for val in mydict.values():
    > try: vals.extend(val)
    > except: vals.append(val)


    >>> l = []
    >>> l.extend((1, 2))
    >>> l

    [1, 2]
    >>> l.extend('ab')
    >>> l

    [1, 2, 'a', 'b']
    >>>



    --
    bruno desthuilliers
    python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
    p in ''.split('@')])"
     
    Bruno Desthuilliers, Jul 31, 2006
    #7
  8. David Zaret

    David Zaret Guest

    thanks for the many responses.

    i have zero control over the dict. in practice, i'm using turbogears
    which is "automatically" populating the result dict with zero-to-many
    choices from a generated list of HTML checkboxes. the user can select
    none, one, or many, and submit. cherrypy packs the **kwargs arg full of
    the selection, as i described in my op.

    using a try/exception case to switch between append and extend will not
    work. the scalar, coming back as a string, can certainly be iterated
    and i'll end up with a bunch of characters in my list.

    i like what's posted below - that's more compact - and at least closer
    to what i was looking for.

    thanks again, great newsgroup.

    ---- dz




    Bruno Desthuilliers wrote:
    > David Zaret wrote:
    >> i have a dict with a particular key - the values for this key will be
    >> None, one valid scalar, or a list:
    >>
    >> {mykey, None}
    >> {mykey, "foo"}
    >> {mykey, ["bar", "baz"]}
    >>
    >> let's ignore the None case - in the case of the one or many values, i
    >> want to suck the values into a list. here's one way to do this:
    >>
    >> if mydict.has_key(mykey):
    >> vals=[]
    >> _v = mydict[mykey]
    >> if isinstance(_v, types.ListType):
    >> vals.extend(_v)
    >> else:
    >> vals.append(_v)
    >> # now we can safely iterate through acts
    >> for val in vals:
    >> .....
    >>
    >>
    >> my way is ugly. what's a better way?

    >
    > If you have control over the dict's creation and 'filling', you may want
    > to handle the case there - eventually using a custom dict-like object
    > that stores everything (but None) in lists. The implementation code for
    > this object will not be less ugly than the one above, but at least
    > ugliness will be hidden away !-)
    >
    > Else, you can shorten the code a bit (NB : ignoring the 'None' case...):
    >
    > v = d[k]
    > v = ([v], v)[isinstance(v, list)]
    >
    > And this can be hidden away in a function:
    >
    > def get_as_list(d, k):
    > v = d[k]
    > return ([v], v)[isinstance(v, list)]
    >
    > vals = get_as_list(mydict, mykey)
    >
    >
    > I don't like using isinstance() tests too much, but it depends on the
    > context...
    >
    > HTH
    >
     
    David Zaret, Jul 31, 2006
    #8
  9. Paul Rubin wrote:
    > Bruno Desthuilliers <> writes:
    >> Too much useless lookup IMHO...

    >
    > Actually, you, me, and Amit all mis-read David's original exapmle.


    Actually, I plea not guilty - cf my answer to the OP !-)

    --
    bruno desthuilliers
    python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
    p in ''.split('@')])"
     
    Bruno Desthuilliers, Jul 31, 2006
    #9
  10. David Zaret wrote:
    > thanks for the many responses.
    >
    > i have zero control over the dict. in practice, i'm using turbogears
    > which is "automatically" populating the result dict with zero-to-many
    > choices from a generated list of HTML checkboxes. the user can select
    > none, one, or many, and submit. cherrypy packs the **kwargs arg full of
    > the selection, as i described in my op.


    Are you sure you get mydict[mykey]==None if the user doesn't check any
    of the checkboxes ? According to html specs, the form's dataset
    shouldn't have the key at all in this case.

    > using a try/exception case to switch between append and extend will not
    > work.


    Nope.

    > the scalar, coming back as a string, can certainly be iterated
    > and i'll end up with a bunch of characters in my list.


    Yes.

    > i like what's posted below


    Thanks - and BTW, please, don't top-post...

    --
    bruno desthuilliers
    python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
    p in ''.split('@')])"
     
    Bruno Desthuilliers, Jul 31, 2006
    #10
  11. David Zaret

    Amit Khemka Guest

    oops ! my mistake :-D

    On 7/31/06, Bruno Desthuilliers <> wrote:
    > Amit Khemka wrote:
    > > how about:
    > >
    > > vals = []
    > > for val in mydict.values():
    > > try: vals.extend(val)
    > > except: vals.append(val)

    >
    > >>> l = []
    > >>> l.extend((1, 2))
    > >>> l

    > [1, 2]
    > >>> l.extend('ab')
    > >>> l

    > [1, 2, 'a', 'b']


    Oops, my mistake ... jumped in too quickly !

    cheers,
    --
    ----
    Amit Khemka -- onyomo.com
    Home Page: www.cse.iitd.ernet.in/~csd00377
    Endless the world's turn, endless the sun's Spinning, Endless the quest;
    I turn again, back to my own beginning, And here, find rest.
     
    Amit Khemka, Jul 31, 2006
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Skip Montanaro
    Replies:
    0
    Views:
    426
    Skip Montanaro
    Aug 15, 2003
  2. Menghan Zheng
    Replies:
    1
    Views:
    281
    alex23
    Apr 20, 2010
  3. Cameron Simpson
    Replies:
    6
    Views:
    361
    alex23
    Apr 21, 2010
  4. macm
    Replies:
    11
    Views:
    623
    Alexander Gattin
    Nov 11, 2010
  5. Steven D'Aprano
    Replies:
    12
    Views:
    190
    Roy Smith
    Jan 19, 2013
Loading...

Share This Page