views:

137

answers:

4

What's the best one-liner replacement for the code below? I'm sure there's a smarter way.

choices = ((1, 'ONE'), (2, 'TWO'), (3, 'THREE'))
some_int = 2
for choice in choices:
    if choice[0] == some_int:
        label = choice[1]
        break;
# label == 'TWO'
+6  A: 

You could use a dict.

>>> choices = { 1: 'ONE', 2: 'TWO', 3: 'THREE' }
>>> label = choices[2]
>>> label
'TWO'
danben
The data structure is a two-tuple since that's how you define field choices in Django.
Sam
+10  A: 
labels = dict(choices)
label = labels[some_int]

you could, of course, join this into an one-liner, if you don't need labels anywhere else.

SilentGhost
I knew it had to be simple!
Sam
+3  A: 

If you're really looking for a one liner...

label = dict(choices)[some_int]

that is,

>>> choices = ((1, 'ONE'), (2, 'TWO'), (3, 'THREE'))
>>> dict(choices)[1]
'ONE'
jgeewax
+5  A: 

For a one-off search, if you're committed to starting with that data structure and can't amortize the time it takes to build it into a dictionary, and don't know whether the starting structure is sorted (so that bisection-search is not an option), there are no substantially faster algorithms than simple linear search. You can express it elegantly, e.g. in Python 2.6 or better:

label = next((lab for cho, lab in choices if cho==someint), None)

assuming you want the label to be None if no choice matches -- or if you want an exception to be raised in that case, just

label = next(lab for cho, lab in choices if cho==someint)

or in older Python versions

label = (lab for cho, lab in choices if cho==someint).next()

but I doubt performance will change much (easy to measure with timeit if you care, but in that case you need to provide some realistic examples of choices -- typical lengths, chance of no choice being acceptable, etc, etc).

Alex Martelli