If you don't care where the matching element is, then use:
found = x in somelist
If you do care, then use a LBYL style with a conditional expression:
i = somelist.index(x) if x in somelist else None
Answer from Raymond Hettinger on Stack OverflowIf you don't care where the matching element is, then use:
found = x in somelist
If you do care, then use a LBYL style with a conditional expression:
i = somelist.index(x) if x in somelist else None
implement your own index for list?
class mylist(list):
def index_withoutexception(self,i):
try:
return self.index(i)
except:
return -1
So, you can use list, and with your index2, return what you want in case of error.
You can use it like this:
l = mylist([1,2,3,4,5]) # This is the only difference with a real list
l.append(4) # l is a list.
l.index_withoutexception(19) # return -1 or what you want
Python index of item in list without error? - Stack Overflow
How to tell python to ignore 'list out of index range' error?
indexing - Python list.index throws exception when index not found - Stack Overflow
Best way to handle list.index(might-not-exist) in python? - Stack Overflow
Hi all,
today it happened once again that I could really use a .get(idx[, default]) method on python lists. Here is a brief example why it could be useful (I know there are many alternative solutions to this specific problem here, so please focus generally on the idea of .get for lists).
file_name = 'test.png'
if '.' in file_name:
extension = file_name.rsplit('.', maxsplit=1)[1]
else:
extension = ''If we had such a method we could make the code much more concise
file_name = 'test.png'
extension = file_name.rsplit('.', maxsplit=1).get(1, '')I wonder why this useful method does not exist, especially since it is available for dicts.
dd = {'a': 'AAA'}
print(f"{dd['a']}; {dd.get('a')}; {dd.get('c')}; {dd.get('c', 'nothing here')}; ")
# AAA; AAA; None; nothing here;Thoughts / ideas why this is not present? Are there valid reasons not to have this method? Is it not available because someone has to invest the work to code it? How could something like this be initiated? :)
a = [1]
try:
index_value = a.index(44)
except ValueError:
index_value = -1
How about this?
I agree with the general solution that was pointed out, but I'd like to look a bit more into the approaches that were explained in the answers and comments to see which one is more efficient and in which situations.
First of all, the three basic approaches:
>>> def my_index(L, obj):
... for i, el in enumerate(L):
... if el == obj:
... return i
... return -1
...
>>> def my_index2(L, obj):
... try:
... return L.index(obj)
... except ValueError:
... return -1
...
>>> def my_index3(L, obj):
... if obj in L:
... return L.index(obj)
... return -1
...
The first and second solutions scan the list only once, and so you may think that they are faster than the third one because it scans the list twice. So let's see:
>>> timeit.timeit('my_index(L, 24999)', 'from __main__ import my_index, L', number=1000)
1.6892211437225342
>>> timeit.timeit('my_index2(L, 24999)', 'from __main__ import my_index2, L', number=1000)
0.403195858001709
>>> timeit.timeit('my_index3(L, 24999)', 'from __main__ import my_index3, L', number=1000)
0.7741198539733887
Well the second is really the fastest, but you can notice that the first one is much slower than the third one, even though it scans the list only once. If we increase the size of the list things does not change much:
>>> L = list(range(2500000))
>>> timeit.timeit('my_index(L, 2499999)', 'from __main__ import my_index, L', number=100)
17.323430061340332
>>> timeit.timeit('my_index2(L, 2499999)', 'from __main__ import my_index2, L', number=100)
4.213982820510864
>>> timeit.timeit('my_index3(L, 2499999)', 'from __main__ import my_index3, L', number=100)
8.406487941741943
The first one is still 2x times slower.
and if we search something that it's not in the list things get even worse for the first solution:
>>> timeit.timeit('my_index(L, None)', 'from __main__ import my_index, L', number=100)
19.055058002471924
>>> timeit.timeit('my_index2(L, None)', 'from __main__ import my_index2, L', number=100)
5.785136938095093
>>> timeit.timeit('my_index3(L, None)', 'from __main__ import my_index3, L', number=100)
5.46164608001709
As you can see in this case the third solution beats even the second one, and both are almost 4x faster than the python code. Depending on how often you expect the search to fail you want to choose #2 or #3(even though in 99% of the cases number #2 is better).
As a general rule, if you want to optimize something for CPython then you want to do as much iterations "at C level" as you can. In your example iterating using a for loop is exactly something you do not want to do.
I'm trying to write a function that check the win condition in tic tac toe board:
win=False
def wincheck(marker,board):
global win
for index,items in enumerate(board):
if board[index] == marker and board[index+1] == marker and board[index+2] == marker:
win=True
break
if board[index] == marker and board[index+3] == marker and board[index+6] == marker:
win=True
break
if board[index] == marker and board[index+4] == marker and board[index+8] == marker:
win=True
break
return winFor my board of 1-9:
originalboard =[1,2,3,4,5,6,7,8,9]
def board_display(board):
print("_" *6)
for row in range(3):
print("".join((f"|{board[row*3+ position]}" for position in range(3))) + "|")
print("_" *6)The problem is the wincheck function will return list out of index range error because index + 8 for index =2 for example is out of my table range and I don't want to widen my table list because it will screw up the board_display function
Because -1 is itself a valid index. It could use a different value, such as None, but that wouldn't be useful, which -1 can be in other situations (thus str.find()), and would amount simply to error-checking, which is exactly what exceptions are for.
Well, the special value would actually have to be None, because -1 is a valid index (meaning the last element of a list).
You can emulate this behavior by:
idx = l.index(x) if x in l else None
There is no global solution that just sets the problem variable to NULL and continuous on with normal program flow. This appears to be the only way:
try:
variable=values[5]
except:
variable='error'
You'll have to change the original one liner to a 4 liner everywhere you use a list variable. It is the most appropriate way since it allows specific response for different variables, but it is a shame that your 10,000 line program is probably going to end up being 30,000 lines just to deal with an index out of range error. Furthermore, you cannot really use referenced lists in equations do to the lack of global error handling in python, which will bulk it up even more. For example:
string_var = "first name: " + values[5] + "last name: " + values[6]
Will not work for your program since you are not 110% certain what your lists will contain (only 99% certain). You'll have to rewrite this using multiple discrete exception handling for each list item, or one exception that has if statements for each discrete list item.
add this global function to your code
def set_var(value):
if len(value) <= 5:
return value[5]
else:
return "None"
then you can use it throughout your code.
variable = set_var(variable)