unpacking vars from list of tuples

Discussion in 'Python' started by Ross, Sep 15, 2009.

  1. Ross

    Ross Guest

    I'm inexperienced with some of the fancy list slicing syntaxes where
    python shines.

    If I have a list of tuples:

    k=[("a", "bob", "c"), ("p", "joe", "d"), ("x", "mary", "z")]

    and I want to pull the middle element out of each tuple to make a new
    list:

    myList = ["bob", "joe", "mary"]

    is there some compact way to do that? I can imagine the obvious one
    of

    myList = []
    for a in k:
    myList.append(a[1])

    But I'm guessing Python has something that will do that in one line...

    Any suggestion is appreciated...

    Ross.
     
    Ross, Sep 15, 2009
    #1
    1. Advertising

  2. Ross

    Chris Rebert Guest

    On Tue, Sep 15, 2009 at 2:51 PM, Ross <> wrote:
    > I'm inexperienced with some of the fancy list slicing syntaxes where
    > python shines.
    >
    > If I have a list of tuples:
    >
    >   k=[("a", "bob", "c"), ("p", "joe", "d"), ("x", "mary", "z")]
    >
    > and I want to pull the middle element out of each tuple to make a new
    > list:
    >
    > myList = ["bob", "joe", "mary"]
    >
    > is there some compact way to do that?  I can imagine the obvious one
    > of
    >
    > myList = []
    > for a in k:
    >   myList.append(a[1])
    >
    > But I'm guessing Python has something that will do that in one line...


    Indeed:

    myList = [a[1] for a in k]

    Google for "list comprehension python".

    Cheers,
    Chris
    --
    http://blog.rebertia.com
     
    Chris Rebert, Sep 15, 2009
    #2
    1. Advertising

  3. Ross

    Andre Engels Guest

    On Tue, Sep 15, 2009 at 11:51 PM, Ross <> wrote:
    > I'm inexperienced with some of the fancy list slicing syntaxes where
    > python shines.
    >
    > If I have a list of tuples:
    >
    >   k=[("a", "bob", "c"), ("p", "joe", "d"), ("x", "mary", "z")]
    >
    > and I want to pull the middle element out of each tuple to make a new
    > list:
    >
    > myList = ["bob", "joe", "mary"]
    >
    > is there some compact way to do that?  I can imagine the obvious one
    > of
    >
    > myList = []
    > for a in k:
    >   myList.append(a[1])
    >
    > But I'm guessing Python has something that will do that in one line...
    >
    > Any suggestion is appreciated...


    You can use a list comprehension:

    myList = [a[1] for a in k]




    --
    André Engels,
     
    Andre Engels, Sep 15, 2009
    #3
  4. On 15 Sep., 23:51, Ross <> wrote:

    > If I have a list of tuples:
    >
    >    k=[("a", "bob", "c"), ("p", "joe", "d"), ("x", "mary", "z")]
    >
    > and I want to pull the middle element out of each tuple to make a new
    > list:
    >
    > myList = ["bob", "joe", "mary"]


    if a tuple is OK: zip(*k)[1]
     
    Wolfram Hinderer, Sep 15, 2009
    #4
  5. Ross

    Ross Guest

    On Sep 15, 6:00 pm, Andre Engels <> wrote:
    > On Tue, Sep 15, 2009 at 11:51 PM, Ross <> wrote:
    > > I'm inexperienced with some of the fancy list slicing syntaxes where
    > > python shines.

    >
    > > If I have a list of tuples:

    >
    > >   k=[("a", "bob", "c"), ("p", "joe", "d"), ("x", "mary", "z")]

    >
    > > and I want to pull the middle element out of each tuple to make a new
    > > list:

    >
    > > myList = ["bob", "joe", "mary"]

    >
    > > is there some compact way to do that?  I can imagine the obvious one
    > > of

    >
    > > myList = []

    Thanks both Chris and André. That's quite obvious once it's pointed
    out for me. Thanks especially for the terminology that will make
    learning the related concepts a bit easier.

    Ross


    > > for a in k:
    > >   myList.append(a[1])

    >
    > > But I'm guessing Python has something that will do that in one line...

    >
    > > Any suggestion is appreciated...

    >
    > You can use a list comprehension:
    >
    > myList = [a[1] for a in k]
    >
    > --
    > André Engels,
     
    Ross, Sep 15, 2009
    #5
  6. Ross

    Tim Chase Guest

    > If I have a list of tuples:
    >
    > k=[("a", "bob", "c"), ("p", "joe", "d"), ("x", "mary", "z")]
    >
    > and I want to pull the middle element out of each tuple to make a new
    > list:
    >
    > myList = ["bob", "joe", "mary"]
    >
    > is there some compact way to do that? I can imagine the obvious one
    > of
    >
    > myList = []
    > for a in k:
    > myList.append(a[1])
    >
    > But I'm guessing Python has something that will do that in one line...


    To add some readability to the other suggested solutions, I'd use
    tuple unpacking

    my_list = [name for status, name, code in k]

    Not knowing what [0] and [2] are, I randomly designated them as
    "status" and "code", but you likely have your own meanings. If
    you don't, you can always just use the "_" convention:

    my_list = [name for _, name, _ in k]
    # or
    my_list = [name for (_, name, _) in k]

    As an aside, "my_list" is preferred over "myList" in common
    Python practice. I don't know if there's a preferred convention
    for "with vs without" the parens in such a tuple-unpacking list
    comprehension.

    -tkc
     
    Tim Chase, Sep 15, 2009
    #6
  7. Ross

    Ross Guest

    Thanks Tim,

    That's actually the stuff I was trying to remember.

    my_list = [name for _, name, _ in k]

    I recalled using some underscores for nice dense unnamed variable
    unpacking before, but couldn't recall the process.

    Thanks for that.

    Ross.


    On 15-Sep-09, at 6:33 PM, Tim Chase wrote:

    >> If I have a list of tuples:
    >> k=[("a", "bob", "c"), ("p", "joe", "d"), ("x", "mary", "z")]
    >> and I want to pull the middle element out of each tuple to make a new
    >> list:
    >> myList = ["bob", "joe", "mary"]
    >> is there some compact way to do that? I can imagine the obvious one
    >> of
    >> myList = []
    >> for a in k:
    >> myList.append(a[1])
    >> But I'm guessing Python has something that will do that in one
    >> line...

    >
    > To add some readability to the other suggested solutions, I'd use
    > tuple unpacking
    >
    > my_list = [name for status, name, code in k]
    >
    > Not knowing what [0] and [2] are, I randomly designated them as
    > "status" and "code", but you likely have your own meanings. If you
    > don't, you can always just use the "_" convention:
    >
    > my_list = [name for _, name, _ in k]
    > # or
    > my_list = [name for (_, name, _) in k]
    >
    > As an aside, "my_list" is preferred over "myList" in common Python
    > practice. I don't know if there's a preferred convention for "with
    > vs without" the parens in such a tuple-unpacking list comprehension.
    >
    > -tkc
    >
    >
    >
    >
    >
    >
    >
     
    Ross, Sep 16, 2009
    #7
  8. Ross

    Ross Guest

    Cool - Now that would be some seriously dense, efficient code! Will
    have to play with numpy sometime.


    R.


    On 17-Sep-09, at 12:25 PM, Chris Colbert wrote:

    > if you have numpy installed:
    >
    >
    > ln[12]: import numpy as np
    > In [13]: k = np.array([('a', 'bob', 'c'), ('p', 'joe', 'd'), ('x',
    > 'mary', 'z')])
    >
    > In [14]: k
    > Out[14]:
    > array([['a', 'bob', 'c'],
    > ['p', 'joe', 'd'],
    > ['x', 'mary', 'z']],
    > dtype='|S4')
    >
    > In [15]: k[:,1]
    > Out[15]:
    > array(['bob', 'joe', 'mary'],
    > dtype='|S4')
     
    Ross, Sep 17, 2009
    #8
  9. Ross

    Ross Guest

    Not this one the other one, from a dictionary

    Learning my way around list comprehension a bit. I wonder if
    someone has a better way to solve this issue. I have a two element
    dictionary, and I know one of the keys but not the other, and I want
    to look up the other one.

    So I have this dictionary:

    aDict = {'a': 'bob', 'b': 'stu'}

    I know that the dictionary contains two keys/value pairs, but I
    don't know the values nor that the keys will be 'a' and 'b'. I
    finally get one of the keys passed to me as variable BigOne. e.g.:

    BigOne = "a"

    The other key, call it littleOne remains unknown. It might be "b"
    but could be "c", "x", etc... I later need to access both values...

    I have something that works, with list comprehension - but wonder if
    there's a more brief/elegant way to get there:

    BigValu = aDict[BigOne]
    temp = [ thing for thing in aDict if thing != BigOne ]
    LittleValu = aDict[ temp[0] ]

    Any thoughts?

    - Ross.
     
    Ross, Sep 18, 2009
    #9
  10. Ross

    Ishwor Guest

    Re: Not this one the other one, from a dictionary

    Ross
    Hi.

    > So I have this dictionary:
    >
    > aDict = {'a': 'bob', 'b': 'stu'}


    Yes.

    > I know that the dictionary contains two keys/value pairs,  but I don't know
    > the values nor that the keys will be 'a' and 'b'.   I finally get one of the
    > keys passed to me as variable BigOne. e.g.:
    >
    > BigOne = "a"


    Right. aDict[BigOne] will give you - 'bob' which may/maynot be what
    you want by the looks of it, you want aDict[BigOne].

    >>> aDict.keys()

    ['a', 'b']
    >>> aDict.values()

    ['bob', 'stu']

    keys() / values() return list so you do not have to worry about
    explicitly getting list.

    > The other key, call it  littleOne remains unknown.  It might be "b" but
    > could be "c", "x", etc...   I later need to access both values...
    >
    > I have something that works, with list comprehension - but wonder if there's
    > a more brief/elegant way to get there:


    If you know the dictionary name in this case aDict (which you don't
    mention you know or not), you can just traverse it using easily as
    such:
    >>>for k in aDict:

    print k, aDict[k];

    >>> [[i,a] for i in aDict]

    [['a', 'bob'], ['b', 'stu']]
    >>> [[i,a] for i in aDict][0]

    ['a', 'stu']
    >>> [[i,a] for i in aDict][0][0]

    'a'
    >>> [[i,a] for i in aDict][0][1]

    'bob'


    --
    Regards,
    Ishwor Gurung
     
    Ishwor, Sep 18, 2009
    #10
  11. Ross

    Tim Chase Guest

    Re: Not this one the other one, from a dictionary

    > Learning my way around list comprehension a bit. I wonder if
    > someone has a better way to solve this issue. I have a two element
    > dictionary, and I know one of the keys but not the other, and I want
    > to look up the other one.


    Several ways occur to me. Of the various solutions I played
    with, this was my favorite (requires Python2.4+ for generator
    expressions):

    d = {'a': 'alice', 'b':'bob'}
    known = 'a'
    other_key, other_value = (
    (k,v)
    for k,v
    in d.iteritems()
    if k != known
    ).next()

    If you just want one or the other, you can simplify that a bit:

    other_key = (k for k in d.iterkeys() if k != known).next()
    other_key = (k for k in d if k != known).next()

    or

    other_value = (v for k,v in d.iteritems() if k != known).next()

    If you're using pre-2.4, you might tweak the above to something like

    other_key, other_value = [
    (k,v)
    for k,v
    in d.iteritems()
    if k != known
    ][0]
    other_key = [k for k in d if k != known)[0]
    other_value = [k for k in d.iteritems if k != known][0]

    Hope this helps,

    -tkc
     
    Tim Chase, Sep 18, 2009
    #11
  12. Ross

    Ross Guest

    Re: Not this one the other one, from a dictionary

    Thanks Tim (and Ishwor) for the suggestions, those are structures
    that somewhat new to me - looks good! I'll play with those. At
    this rate I may soon almost know what I'm doing.

    Rgds
    Ross.


    On 18-Sep-09, at 1:19 PM, Tim Chase wrote:

    >> Learning my way around list comprehension a bit. I wonder if
    >> someone has a better way to solve this issue. I have a two
    >> element dictionary, and I know one of the keys but not the other,
    >> and I want to look up the other one.

    >
    > Several ways occur to me. Of the various solutions I played with,
    > this was my favorite (requires Python2.4+ for generator expressions):
    >
    > d = {'a': 'alice', 'b':'bob'}
    > known = 'a'
    > other_key, other_value = (
    > (k,v)
    > for k,v
    > in d.iteritems()
    > if k != known
    > ).next()
    >
    > If you just want one or the other, you can simplify that a bit:
    >
    > other_key = (k for k in d.iterkeys() if k != known).next()
    > other_key = (k for k in d if k != known).next()
    >
    > or
    >
    > other_value = (v for k,v in d.iteritems() if k != known).next()
    >
    > If you're using pre-2.4, you might tweak the above to something like
    >
    > other_key, other_value = [
    > (k,v)
    > for k,v
    > in d.iteritems()
    > if k != known
    > ][0]
    > other_key = [k for k in d if k != known)[0]
    > other_value = [k for k in d.iteritems if k != known][0]
    >
    > Hope this helps,
    >
    > -tkc
    >
    >
    >
    >
    >
     
    Ross, Sep 18, 2009
    #12
  13. Re: Not this one the other one, from a dictionary

    2009/9/18 Ross <>:
    >
    > Learning my way around list comprehension a bit.   I wonder if someone has a
    > better way to solve this issue.  I have a two element dictionary, and I know
    > one of the keys but not the other, and I want to look up the other one.
    >
    > So I have this dictionary:
    >
    > aDict = {'a': 'bob', 'b': 'stu'}
    >
    > I know that the dictionary contains two keys/value pairs,  but I don't know
    > the values nor that the keys will be 'a' and 'b'.   I finally get one of the
    > keys passed to me as variable BigOne. e.g.:
    >
    > BigOne = "a"
    >
    > The other key, call it  littleOne remains unknown.  It might be "b" but
    > could be "c", "x", etc...   I later need to access both values...
    >
    > I have something that works, with list comprehension - but wonder if there's
    > a more brief/elegant way to get there:
    >
    > BigValu = aDict[BigOne]
    > temp =  [ thing for thing in aDict if thing != BigOne ]
    > LittleValu = aDict[ temp[0] ]
    >
    > Any thoughts?
    >
    > - Ross.
    >
    > --
    > http://mail.python.org/mailman/listinfo/python-list
    >


    Hi,
    not a list comprehension, but another useful approach to get the
    complement of (a) given item(s) might be the set operations.
    (As you are working with dict keys, the requirements for set elements
    are automatically fulfilled.

    >>> data_dict = {'a': 'bob', 'b': 'stu'}
    >>> not_wanted_key = "a"
    >>> other_key = (set(data_dict.iterkeys()) - set([not_wanted_key,])).pop()
    >>> other_key

    'b'
    >>> data_dict[other_key]

    'stu'
    >>>


    vbr
     
    Vlastimil Brom, Sep 18, 2009
    #13
  14. Re: Not this one the other one, from a dictionary

    Vlastimil Brom <> wrote:
    >>>> other_key = (set(data_dict.iterkeys()) - set([not_wanted_key,])).pop()


    other_key = set(data_dict.iterkeys()).difference([not_wanted]).pop()
    saves you the construction of an unnecessary set instance. At the
    cost of a bit more verbosity, you can get rid of a second set:

    key_set = set(data_dict.iterkeys())
    key_set.difference_update([not_wanted_key])
    other_key = key_set.pop()

    although the loss of clarity compared to the one liner can't be
    worth the miniscule benefit in this case.

    --
    \S

    under construction
     
    Sion Arrowsmith, Sep 22, 2009
    #14
  15. Ross

    Jean Daniel Guest

    Re: Not this one the other one, from a dictionary

    Building on the answers of the others, a simple one liner, no side
    effect, not the fastest I guess:

    >>> d={'a': 'bob', 'b': 'stu'}
    >>> set( d.keys() ).difference( [ 'a' ] ).pop()

    'b'

    Note the square brackets for the parameter of difference(). 'The
    string 'a' and the list [ 'a' ] are both iterable but really are
    different.
     
    Jean Daniel, Sep 22, 2009
    #15
  16. Re: Not this one the other one, from a dictionary

    Thanks for the elaboration;
    in retrospect, given the simple requirement, that there are only two
    dict keys, one of which is know and the other to be determined, maybe
    just the direct dict methods are appropriate, e.g.

    d = {'a': 'bob', 'b': 'stu'}
    d_copy = dict(d)
    d_copy.pop("a")
    'bob'
    d_copy.popitem()
    ('b', 'stu')

    vbr
     
    Vlastimil Brom, Sep 22, 2009
    #16
    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. Replies:
    5
    Views:
    580
    Thomas J. Gritzan
    Oct 6, 2006
  2. tuples within tuples

    , Oct 26, 2007, in forum: Python
    Replies:
    12
    Views:
    620
    Dennis Lee Bieber
    Oct 27, 2007
  3. Stef Mientki
    Replies:
    0
    Views:
    291
    Stef Mientki
    Aug 15, 2009
  4. Stef Mientki
    Replies:
    0
    Views:
    1,131
    Stef Mientki
    Aug 15, 2009
  5. Jon Reyes
    Replies:
    18
    Views:
    274
    Mitya Sirenef
    Feb 19, 2013
Loading...

Share This Page