Velocity Reviews > Searching through a list of tuples

# Searching through a list of tuples

Repton
Guest
Posts: n/a

 07-12-2005
I often find myself storing data in a list of tuples, and I want to ask
questions like "what is the index of the first tuple whose 3rd element
is x", or "give me the first tuple whose 2nd element is y".

I know I can do [elem for elem in lst if elem[3] == x][0] or (elem for
elem in lst if elem[2] == y).next() but it feels kinda ugly; is there a
better way?

(something like lst.index(x, key=..) or lst.find(y, key=..) would be
nice)

--
John.

Peter Hansen
Guest
Posts: n/a

 07-12-2005
Repton wrote:
> I often find myself storing data in a list of tuples, and I want to ask
> questions like "what is the index of the first tuple whose 3rd element
> is x", or "give me the first tuple whose 2nd element is y".
>
> I know I can do [elem for elem in lst if elem[3] == x][0] or (elem for
> elem in lst if elem[2] == y).next() but it feels kinda ugly; is there a
> better way?
>
> (something like lst.index(x, key=..) or lst.find(y, key=..) would be
> nice)

If the latter form would make you happy, why not just write a simple
utility function that does what you want (by using the first technique,
if you wish), and then calling it will be as simple as lst.index(....)

And no, since you are basically doing a form of pattern matching, I
don't think there's a shortcut.

-Peter

Peter Otten
Guest
Posts: n/a

 07-12-2005
Repton wrote:

> I often find myself storing data in a list of tuples, and I want to ask
> questions like "what is the index of the first tuple whose 3rd element
> is x", or "give me the first tuple whose 2nd element is y".
>
> I know I can do [elem for elem in lst if elem[3] == x][0] or (elem for
> elem in lst if elem[2] == y).next() but it feels kinda ugly; is there a
> better way?
>
> (something like lst.index(x, key=..) or lst.find(y, key=..) would be
> nice)

>>> items = [(1, "a", 10), (2, "b", 20), (3, "c", 30)]
>>> class Key(object):

.... def __init__(self, key):
.... self.key = key
.... def __eq__(self, other):
.... return self.key(other)
....
>>> items.index(Key(lambda x: x[2] == 20))

1
>>> items.index(Key(lambda x: x[1] == "c"))

2

A cleaner and probably faster solution would be to subclass list and
override index()/find().

Peter

Scott David Daniels
Guest
Posts: n/a

 07-12-2005
Peter Otten wrote:
> Repton wrote:
>
>>I often find myself storing data in a list of tuples, and I want to ask
>>questions like "what is the index of the first tuple whose 3rd element
>>is x",

iter(n for n, elem in enumerate(lst) if elem[3] == x).next()

>>or "give me the first tuple whose 2nd element is y".

iter(elem in lst if elem[3] == x).next()

Does this look any better? At least it stops when the answer is found.

--Scott David Daniels
http://www.velocityreviews.com/forums/(E-Mail Removed)

Alan Green
Guest
Posts: n/a

 07-12-2005
Peter Otten wrote:
> Repton wrote:
>
> > I often find myself storing data in a list of tuples, and I want to ask
> > questions like "what is the index of the first tuple whose 3rd element
> > is x", or "give me the first tuple whose 2nd element is y".

> >>> items = [(1, "a", 10), (2, "b", 20), (3, "c", 30)]
> >>> class Key(object):

> ... def __init__(self, key):
> ... self.key = key
> ... def __eq__(self, other):
> ... return self.key(other)
> ...
> >>> items.index(Key(lambda x: x[2] == 20))

> 1

Neat solution.

I'd add an extra kind of Key, since finding tuples where a given
position is equal to a given value seems to be the common case:

>>> class EqualKey(Key):

.... def __init__(self, pos, val):
.... super(EqualKey, self).__init__(lambda x: x[pos] == val)
....
>>> items.index(EqualKey(2, 20))

1

Alan

Peter Otten
Guest
Posts: n/a

 07-13-2005
Scott David Daniels wrote:

> iter(elem*in*lst*if*elem[3]*==*x).next()
>
> Does this look any better?**At*least*it*stops*when*the*answer*is*found.

Next time you'll recommend

if (a>b) == True:
# ...

Watch out, you're on a slippery slope here

Peter