unpacking vars from list of tuples

879 views
Skip to first unread message

Ross

unread,
Sep 15, 2009, 5:51:04 PM9/15/09
to
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.

Chris Rebert

unread,
Sep 15, 2009, 5:56:49 PM9/15/09
to Ross, pytho...@python.org

Indeed:

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

Google for "list comprehension python".

Cheers,
Chris
--
http://blog.rebertia.com

Andre Engels

unread,
Sep 15, 2009, 6:00:21 PM9/15/09
to Ross, pytho...@python.org

You can use a list comprehension:

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


--
André Engels, andre...@gmail.com

Wolfram Hinderer

unread,
Sep 15, 2009, 6:26:41 PM9/15/09
to
On 15 Sep., 23:51, Ross <ros...@gmail.com> 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]

Ross

unread,
Sep 15, 2009, 6:31:31 PM9/15/09
to
On Sep 15, 6:00 pm, Andre Engels <andreeng...@gmail.com> wrote:
> On Tue, Sep 15, 2009 at 11:51 PM, Ross <ros...@gmail.com> 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, andreeng...@gmail.com

Tim Chase

unread,
Sep 15, 2009, 6:33:53 PM9/15/09
to Ross, pytho...@python.org
> 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

unread,
Sep 15, 2009, 10:12:05 PM9/15/09
to pytho...@python.org
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...
>

Chris Colbert

unread,
Sep 17, 2009, 12:25:41 PM9/17/09
to Ross, pytho...@python.org
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

unread,
Sep 17, 2009, 3:09:18 PM9/17/09
to pytho...@python.org

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

unread,
Sep 18, 2009, 12:28:44 PM9/18/09
to pytho...@python.org

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.

Tim Chase

unread,
Sep 18, 2009, 1:19:08 PM9/18/09
to Ross, pytho...@python.org
> 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

Ishwor

unread,
Sep 18, 2009, 12:59:09 PM9/18/09
to Ross, pytho...@python.org
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[i]] for i in aDict]
[['a', 'bob'], ['b', 'stu']]
>>> [[i,a[i]] for i in aDict][0]
['a', 'stu']
>>> [[i,a[i]] for i in aDict][0][0]
'a'
>>> [[i,a[i]] for i in aDict][0][1]
'bob'


--
Regards,
Ishwor Gurung

Ross

unread,
Sep 18, 2009, 2:48:12 PM9/18/09
to pytho...@python.org
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.

Vlastimil Brom

unread,
Sep 18, 2009, 3:50:03 PM9/18/09
to pytho...@python.org
2009/9/18 Ross <ros...@gmail.com>:

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

Sion Arrowsmith

unread,
Sep 22, 2009, 8:01:37 AM9/22/09
to
Vlastimil Brom <vlastim...@gmail.com> 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

Jean Daniel

unread,
Sep 22, 2009, 1:04:02 PM9/22/09
to Vlastimil Brom, pytho...@python.org
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.

Vlastimil Brom

unread,
Sep 22, 2009, 6:21:39 PM9/22/09
to pytho...@python.org
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

Reply all
Reply to author
Forward
0 new messages