How can I check if a list index exists? - python

Seems as though
if not mylist[1]:
return False
Doesn't work.

You just have to check if the index you want is in the range of 0 and the length of the list, like this
if 0 <= index < len(list):
it is actually internally evaluated as
if (0 <= index) and (index < len(list)):
So, that condition checks if the index is within the range [0, length of list).
Note: Python supports negative indexing. Quoting Python documentation,
If i or j is negative, the index is relative to the end of the string: len(s) + i or len(s) + j is substituted. But note that -0 is still 0.
It means that whenever you use negative indexing, the value will be added to the length of the list and the result will be used. So, list[-1] would be giving you the element list[-1 + len(list)].
So, if you want to allow negative indexes, then you can simply check if the index doesn't exceed the length of the list, like this
if index < len(list):
Another way to do this is, excepting IndexError, like this
a = []
try:
a[0]
except IndexError:
return False
return True
When you are trying to access an element at an invalid index, an IndexError is raised. So, this method works.
Note: The method you mentioned in the question has a problem.
if not mylist[1]:
Lets say 1 is a valid index for mylist, and if it returns a Falsy value. Then not will negate it so the if condition would be evaluated to be Truthy. So, it will return False, even though an element actually present in the list.

In the EAFP style of Python:
try:
mylist[1]
except IndexError:
print "Index doesn't exist!"

In the case of integer-indexed lists, I'd simply do
if 1 < len(mylist):
...
For dicts, you can of course do
if key in mydict:
...

Alternative (but somewhat slower) way of doing it:
if index not in range(len(myList)):
return False
It gets a bit more verbose when accounting for negative indices:
if index not in range(-len(myList), len(myList)):
return False

assert len(mylist) >= abs(index) + int(index >= 0), "Index out of range"
or
assert len(mylist) > abs(index) - int(index < 0), "Index out of range"

Or you can do:
if index in dict(enumerate(mylist)):
return True
Although is will probably be even less efficient than range(len(mylist)). Maybe someone should propose a keys() method for lists that returns the range of the keys in PEP.

The following approach returns the True result for index == 0 and for negative index values (if such an index is valid for the list, for example listIn[-2] for [0, 1, 2]):
def isInListRange(listIn, index):
""" Description: Function to detect if list index out of range
Import: from shared.isInListRange import isInListRange
Test: python -m shared.isInListRange
"""
try:
return True if (index == 0 and len(listIn) > 0) or listIn[index] else False
except:
return False

Related

Can some one help me fix this list sorting code?

When I run this code it doesn't print anything?
I've tried to invert the greater than less than but it's not helping.
def is_sorted(numbers):
''' Return whether or not the list of numbers is sorted '''
for i in numbers:
if numbers[i] < numbers[i + 1]:
print('True')
else:
print('False')
for i in numbers in this case i is each number itself, not the index of each number. That would be for i in range(len(numbers)) though then [i + 1] would go out of bounds on the last iteration.
As an alternative, I would simplify that function to compare each element to the next element by zipping a slice of the list against another slice offset by one. By writing this as a generator expression within all this will short-circuit upon hitting the first False
def is_sorted(numbers):
return all(i <= j for i, j in zip(numbers, numbers[1::]))
For example
>>> is_sorted([1,3,5,7])
True
>>> is_sorted([1,6,2,7,3])
False
Something like this should work:
def is_sorted(numbers):
isSorted = True
for i in numbers:
try:
if i > numbers[numbers.index(i)+1]:
isSorted = False
except:
pass
return isSorted
print(is_sorted([1,2],3,9,3))
You should add the variable, isSorted, because if i > next number, it would print False, but if i < next number, it would print True. You need the try and except, because if there was an error, if it was on the last number, it would be ignored. You also need to change i > numbers[i+1] to i > numbers[numbers.index(i)+1], because to get the next number, we need to add 1 to the index, not the value.

Code to check all list elements are same returns IndexError?

I know the index goes over the index of the last member of the group doing it like this but how do I make the function work properly?
Anyway, the function is meant to check if all the members of a list are the same. I have the same problem with another function which is meant to check if the list is in order. It works with everything else but when it's all same numbers it doesn't.
i = 0
while i < len(list1):
if list1[i] == list1[i + 1]:
i += 1
else:
return False
return True
Error message is: "IndexError: list index out of range"
When i reaches the maximum index within list1, obviously list1[i+1] will be out of bounds. The immediate fix is to start at 1 (and then of course compare downwards) or stop at len(list1)-1.
But you can simplify by comparing all indices to the zeroth.
all([list1[0] == x for x in list1[1:]])
or as a longhand loop
for elem in list1[1:]:
if elem != list1[0]:
return False
return True
The error itself is coming from the line
if list1[i] == list1[i+1]
The portion of the line above is going out of range. An easy fix is to change the while statement to this:
while i < (len(list1)-1):
I believe that should still have the same result as you desire.
Be careful about accessing future items in a list with a while loop.

In this short recursive function `list_sum(aList)`, the finish condition is `if not aList: return 0`. I see no logic in why this condition works

I am learning the recursive functions. I completed an exercise, but in a different way than proposed.
"Write a recursive function which takes a list argument and returns the sum of its integers."
L = [0, 1, 2, 3, 4] # The sum of elements will be 10
My solution is:
def list_sum(aList):
count = len(aList)
if count == 0:
return 0
count -= 1
return aList[0] + list_sum(aList[1:])
The proposed solution is:
def proposed_sum(aList):
if not aList:
return 0
return aList[0] + proposed_sum(aList[1:])
My solution is very clear in how it works.
The proposed solution is shorter, but it is not clear for me why does the function work. How does if not aList even happen? I mean, how would the rest of the code fulfill a not aList, if not aList means it checks for True/False, but how is it True/False here?
I understand that return 0 causes the recursion to stop.
As a side note, executing without if not aList throws IndexError: list index out of range.
Also, timeit-1million says my function is slower. It takes 3.32 seconds while the proposed takes 2.26. Which means I gotta understand the proposed solution.
On the call of the function, aList will have no elements. Or in other words, the only element it has is null. A list is like a string or array. When you create a variable you reserve some space in the memory for it. Lists and such have a null on the very last position which marks the end so nothing can be stored after that point. You keep cutting the first element in the list, so the only thing left is the null. When you reach it you know you're done.
If you don't use that condition the function will try to take a number that doesn't exist, so it throws that error.
You are counting the items in the list, and the proposed one check if it's empty with if not aList this is equals to len(aList) == 0, so both of you use the same logic.
But, you're doing count -= 1, this has no sense since when you use recursion, you pass the list quiting one element, so here you lose some time.
According to PEP 8, this is the proper way:
• For sequences, (strings, lists, tuples), use the fact that empty
sequences are false.
Yes: if not seq:
if seq:
No: if len(seq)
if not len(seq)
Here is my amateur thougts about why:
This implicit check will be faster than calling len, since len is a function to get the length of a collection, it works by calling an object's __len__ method. This will find up there is no item to check __len__.
So both will find up there is no item there, but one does it directly.
not aList
return True if there is no elements in aList. That if statement in the solution covers edge case and checks if input parameter is not empty list.
For understand this function, let's run it step by step :
step 0 :
L=[0,1,2,3,4]
proposed_sum([0,1,2,3,4])
L != []
return l[0] + proposed_sum([1,2,3,4])
step 1 calcul proposed_sum([1,2,3,4]):
proposed_sum([1,2,3,4])
L != []
return l[0] + sum([2,3,4])
step 2 calcul proposed_sum([2,3,4]):
proposed_sum([2,3,4])
L != []
return l[0] + sum([3,4])
step 3 calcul proposed_sum([3,4]):
proposed_sum([3,4])
L != []
return l[0] + sum([4])
step 4 calcul proposed_sum([4]):
proposed_sum([4])
L != []
return l[0] + sum([])
step 5 calcul proposed_sum([]):
proposed_sum([])
L == []
return 0
step 6 replace:
proposed_sum([0,1,2,3,4])
By
proposed_sum([]) + proposed_sum([4]) + proposed_sum([3,4]) + proposed_sum([2,3,4]) + proposed_sum([1,2,3,4])+ proposed_sum([0,1,2,3,4])
=
(0) + 4 + 3 + 2 + 1 + 0
Python considers as False multiple values:
False (of course)
0
None
empty collections (dictionaries, lists, tuples)
empty strings ('', "", '''''', """""", r'', u"", etc...)
any other object whose __nonzero__ method returns False
in your case, the list is evaluated as a boolean. If it is empty, it is considered as False, else it is considered as True. This is just a shorter way to write if len(aList) == 0:
in addition, concerning your new question in the comments, consider the last line of your function:
return aList[0] + proposed_sum(aList[1:])
This line call a new "instance" of the function but with a subset of the original list (the original list minus the first element). At each recursion, the list passed in argument looses an element and after a certain amount of recursions, the passed list is empty.

I want to check if a string is abecedarian

I want to check if a string is abecedarian (in alphabetical order).
def is_abecdarian(s):
index = 0
while index < len(s)-1:
if s[index + 1] > s[index]:
return True
index += 1
return False
print(is_abecdarian('babcd'))
If I switch my False and True around and switch the greater than to less than it works. What I do not understand is 'a' is not greater than 'b', yet when I run the above code it returns True.
The return True statement exits the function, so right now it runs until there are two letters that are in a correct order and then exits.
The way your loop is written, it will return True if any pair of characters is ordered. It only returns False if all pairs fail. The first pair ba fails the if check, but the second pair ab passes and the function returns True.
This isn't right, because if you think about it, you can't know that a string is abecedarian until you've examined all of the characters. You should only be returning True when you're done with the loop. Conversely, as soon as you find a pair of characters that's out of order, it is safe to return False.
That's why flipping the booleans and the < operation works.
You need to return False only if next character is < than current.
If there were no such an occurrence during all the loop then return True.
Here is correct function:
def is_abecdarian(s):
index = 0
while index < len(s)-1:
if s[index + 1] < s[index]:
return False
index += 1
return True
print(is_abecdarian('babcd'))
print(is_abecdarian('abcz'))
Why it's not working has already been explained, so, only to add to what has been explained:
def is_abecdarian(s):
return all(s[i] < s[i+1] for i in range(len(s)-1))
print(is_abecdarian('babcd'))
print(is_abecdarian('ejmpq'))
Where
all(argument) returns True only if all boolean in the argument are True;
s[i] < s[i+1] is a comparison between the i-th element of s to the next one.
s[i] < s[i+1] for i in range(len(s)-1) makes the comparison for all pairs of consecutive elements of s.

How to check whether a list index is present or not

I have the following list
a = ['a','c','d']
I need to check whether the list index 4(or any index) is present on the list or not. Is there a method similar to php isset in python for this(without using exception handling)?
if len(a) > 4:
# list contains fourth element, a[4]
or
try:
a[4] # do something with a[4]
except IndexError:
print "there is no element a[4]"
You can use len() to check whether the Index is present or not.
As len(list) returns something like last_index+1:
In [18]: a = ['a','c','d']
In [19]: len(a)-1 > 4 #or len(a)>4
Out[19]: False
In [20]: len(a)-1 > 2
Out[20]: True
You can always check:
if index < len(a):
# do stuff

Categories