32

I have a list of tuples that look like :

CODES = (
    ('apple', 'reddelicious'),
    ('caramel', 'sweetsticky'),
    ('banana', 'yellowfruit'),
)

What's the best way to check if a value exists in that tuple? For example I want to be able to say:

'apple' in CODES

and get True

Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
9-bits
  • 10,395
  • 21
  • 61
  • 83

2 Answers2

60

You are looking for any():

if any('apple' in code for code in CODES):
    ...

Combined with a simple generator expression, this does the task. The generator expression takes each tuple and yields True if it is contains 'apple'. any() then returns True when the first item it requests returns True (otherwise, False). Hence this does what you want. It also reads nicely - if any of the tuples contain 'apple'.

If you are doing this a massive number of times and need performance, then it might be worth making a set of all of the values to allow you to do this very quickly:

cache = set(itertools.chain.from_iterable(CODES)))

Naturally, constructing this will be slow and use memory, so it wouldn't be a good idea unless you need a lot of performance and will be doing a lot of membership checks.

Gareth Latty
  • 86,389
  • 17
  • 178
  • 183
  • what if instead of just checking for the existence - i wanted to get the second value? In this case "reddelicious"? – 9-bits Feb 28 '13 at 00:02
  • 4
    In that case, you are using the wrong data structure, use a `dict`, then just do `CODES["apple"]` (and catch the `KeyError` if it isn't there). – Gareth Latty Feb 28 '13 at 00:04
  • 1
    @9-bits just use `dic=dict(CODES)`, this will return a dictionary.And then `dic['apple']` will result in `'reddelicious'`. – Ashwini Chaudhary Feb 28 '13 at 00:10
  • @AshwiniChaudhary Well, if the data exists in this format, then yes, but if you are making a literal as in your example, no need to take the extra step, just make a `dict` to begin with. – Gareth Latty Feb 28 '13 at 00:11
  • For those of you still living in Py2.x https://docs.python.org/2/library/functions.html#any ```any()``` is there too! – Marc Dec 10 '15 at 16:01
9

You can use itertools.chain():

Using it with in will result in short-circuiting, similar to any().

In [30]: CODES = (
   ....:     ('apple', 'reddelicious'),
   ....:     ('caramel', 'sweetsticky'),
   ....:     ('banana', 'yellowfruit'),
   ....: )


In [31]: from itertools import chain

In [32]: 'apple' in chain(*CODES)
Out[32]: True

In [33]: 'foo' in chain(*CODES)
Out[33]: False

For performance comparisons you can check my other answer.

Community
  • 1
  • 1
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
  • 2
    +1, This is a reasonable way to do this - I'm not sure how it compares performance-wise. Although you should use `chain.from_iterable()` over `chain(*)`. – Gareth Latty Feb 27 '13 at 23:51
  • @Lattyware I think as both `any()` and my method are doing short-circuiting, so, the performance difference should be negligible for large data. – Ashwini Chaudhary Feb 28 '13 at 00:07