tags:

views:

344

answers:

5

I have a list of integers. I want to know whether the number 13 appears in it and, if so, where. Do I have to search the list twice, as in the code below?

if 13 in intList:
   i = intList.index(13)

In the case of dictionaries, there's a get function which will ascertain membership and perform look-up with the same search. Is there something similar for lists?

+12  A: 

You answered it yourself, with the index() method. That will throw an exception if the index is not found, so just catch that:

def getIndexOrMinusOne(a, x):
  try:
    return a.index(x)
  except ValueError:
    return -1
unwind
Never use an empty except clause. You should do except IndexError.
Bluebird75
that wouldn't work. [].index() throws a ValueError
TokenMacGuy
You're probably abusing lists if you need to do things this way; this looks like a code smell.
John Feminella
Uh? This works, I tested it ... The except is not empty, it contains the return?
unwind
He means you should not do a "global" except but rather specify what you are catching, ValueError, etc.
Paolo Bergantino
by 'empty' he means, I guess, catching all exception types, not only the one you want. This way it's easy to go over some error you weren't planing
kender
But sometimes you can, never say never. I agree in this case naked except is not a good thing.
Ali A
One code smell here is that the list should probably have been a set.
S.Lott
S.Lott: I guess it all depends whether the items are unique or not.
Ali A
@Ali A: not at all, thanks a lot. And thanks to everyone else who commented!
unwind
+8  A: 

It looks like you'll just have to catch the exception...

try:
    i = intList.index(13)
except ValueError:
    i = some_default_value
TokenMacGuy
A: 

Just put what you got in a function and use it:)

You can either use if i in list: return list.index(i) or the try/except, depending on your preferences.

kender
+4  A: 

No, there isn't a direct match for what you asked for. There was a discussion a while back on the Python mailing list about this, and people reached the conclusion that it was probably a code smell if you needed this. Consider using a dict or set instead if you need to test membership that way.

John Feminella
I think you didn't read carefully the question.
vartec
Ah, whoops; you're right. Fixed!
John Feminella
This just condenses the syntax of the original code sample. The performance problem is unaddressed. Python still tests if item in list first, then searches for the index of item in the list.
David Berger
@David: You're right. I should probably just delete the code and focus on the second paragraph, which was my real point. The other solutions all seem to trade the list check for an expensive exception-throw/catching situation.
John Feminella
+2  A: 

You can catch the ValueError exception, or you can do:

i = intList.index(13) if 13 in intList else -1

(Python 2.5+)

BTW. if you're going to do a big batch of similar operations, you might consider building inverse dictionary value -> index.

intList = [13,1,2,3,13,5,13]
indexDict = defaultdict(list)
for value, index in zip(intList, range(len(intList))):
   indexDict[value].append(index)

indexDict[13]
[0, 4, 6]
vartec