How to check if end of list was reached? - python

If have a list, say a=[1,2,3], and I want to see if a[4] is null, is there a way to do that, without using an exception or assertion?

len will tell you the length of the list. To quote the docs:
len(s)
    Return the length (the number of items) of an object. The argument may be a sequence     (string, tuple or list) or a mapping (dictionary).
Of course, if you want to get the final element in a list, tuple, or string, since indexes are 0 based, and the length of an item is the element count, a[len(a)-1] will be the last item.
As an aside, generally, the proper way to access the last element in an object which allows numeric indexing (str, list, tuple, etc) is using a[-1]. Obviously, that does not involve len though.

with a = [1,2,3] :
a[2:3] is [3]
a[3:4] is [ ]
So a[i:i+1] != [ ] tells if is an index of a
a[i:] does the same, but a[i:] creates another list, possible very long, while a[i:i+1] is 1 element if not empty

Here is an approach which I applied in one of the Arcade Challenges from Code Fights.
Basically, the end of a list is defined by:
list length - current index (iteration) == 1
#!/usr/bin/python3
numbers = [1, 3, 5, 8, 10, 13, 16]
list_len = len(numbers)
for n in numbers:
current_idx = numbers.index(n)
print("Current Number:", numbers[current_idx])
list_end = list_len - current_idx
if list_end != 1:
next_idx = current_idx + 1
print("Next Number: ", numbers[next_idx])
else:
print("End Of List!")

Use len
if len(a) <= index:
...
Note: Your question asks how you would find out "if a[4] is null". a[4] isn't anything, which is why you get an IndexError when you try to check it.

a[4] in this case will throw a IndexError exception, which isn't the same as comparing the value of a at index 4 to None. You can have values of None in a list, and if you were to compare values of a, then when you encounter a None, it doesn't mean that the index is not found in the list. For example:
>>> a=[1,None,2]
>>> a[1]==None
True
>>> a[3]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
Since lists are contiguous and indexed sequentially, the correct way to check if an index is in a list is to compare it to the len() of a list, but depending on the application, there are other ways around it, like catching an IndexError, or iteration.
>>> for index, value in enumerate(a):
... print index, value
...
0 1
1 None
2 2

You could write a function which behaves kind of like dict.get() does for dictionaries:
def listget(list_, index, default=None):
"""Return the item for index if index is in the range of the list_,
else default. If default is not given, it defaults to None, so that
this method never raises an IndexError."""
if index >= len(list_) or index < -len(list_):
return default
else:
return list_[index]
Example usage:
>>> names = ["Mark","Frank","James"]
>>> listget(names, 2)
'James'
>>> listget(names,-3)
'Mark'
>>> listget(names,3) # returns None
>>> listget(names,4,0)
0
So it will always return a value and you get no exceptions.

You're not providing a specific use-case, but generally for a list your would use len to see how many elements are in the list.
if len(a) > 3:
# Do something

The general way to check if you're currently looking at the element at the end of a list (in any language) is to compare the current index you're looking at with the length of the list minus one (since indexes start at 0).
a[4] isn't really anything, because it doesn't exist - some languages may implement that as being null (or undefined) but many will simply throw an exception if you try to access it instead.

Here is the logic statement I use to check whether the end of your list has been reached:
arr = [1,3,2,4,5]
#counter for the array
arr_counter = 0
for ele in array:
# check if end of list has been reached
if (arr_counter+1) != len(arr):
#put all your code here
pass
# increment the array counter
arr_counter += 1
Hope this helps ! :)

look here:
https://www.geeksforgeeks.org/python-how-to-get-the-last-element-of-list/
test_list = [1, 4, 5, 6, 3, 5]
# printing original list
print ("The original list is : " + str(test_list))
# First naive method
# using loop method to print last element
for i in range(0, len(test_list)):
if i == (len(test_list)-1):
print ("The last element of list using loop : "+ str(test_list[i]))
# Second naive method
# using reverse method to print last element
test_list.reverse() `enter code here`
print("The last element of list using reverse : "+ str(test_list[0]))

Related

Which item in list - Python

I am making a console game using python and I am checking if an item is in a list using:
if variable in list:
I want to check which variable in that list it was like list[0] for example. Any help would be appreciated :)
You can do it using the list class attribute index as following:
list.index(variable)
Index gives you an integer that matches the location of the first appearance of the value you are looking for, and it will throw an error if the value is not found.
If you are already checking if the value is in the list, then within the if statement you can get the index by:
if variable in list:
variable_at = list.index(variable)
Example:
foo = ['this','is','not','This','it','is','that','This']
if 'This' in foo:
print(foo.index('This'))
Outputs:
3
Take a look at the answer below, which has more complete information.
Finding the index of an item in a list
We may be inspired from other languages such as Javascript and create a function which returns index if item exists or -1 otherwise.
list_ = [5, 6, 7, 8]
def check_element(alist: list, item: any):
if item in alist:
return alist.index(item)
else:
return -1
and the usage is
check1 = check_element(list_, 5)
check2 = check_element(list_, 9)
and this one is for one line lovers
check_element_one_liner = lambda alist, item: alist.index(item) if item in alist else -1
alternative_check1 = check_element_one_liner(list_, 5)
alternative_check2 = check_element_one_liner(list_, 9)
and a bit shorter version :)
check_shorter = lambda a, i: a.index(i) if i in a else -1
Using a librairy you could use numpy's np.where(list == variable).
In vanilla Python, I can think of something like:
idx = [idx for idx, item in enumerate(list) if item == variable][0]
But this solution is not fool proof, for instance, if theres no matching results, it will crash. You could complete this using an if right before:
if variable in list:
idx = [idx for idx, item in enumerate(list) if item == variable][0]
else:
idx = None
I understand that you want to get a sublist containing only the elements of the original list that match a certain condition (in your example case, you want to extract all the elements that are equal to the first element of the list).
You can do that by using the built-in filter function which allows you to produce a new list containing only the elements that match a specific condition.
Here's an example:
a = [1,1,1,3,4]
variable = a[0]
b = list(filter(lambda x : x == variable, a)) # [1,1,1]
This answer assumes that you only search for one (the first) matching element in the list.
Using the index method of a list should be the way to go. You just have to wrap it in a try-except statement. Here is an alternative version using next.
def get_index(data, search):
return next((index for index, value in enumerate(data) if value == search), None)
my_list = list('ABCDEFGH')
print(get_index(my_list, 'C'))
print(get_index(my_list, 'X'))
The output is
2
None
assuming that you want to check that it exists and get its index, the most efficient way is to use list.index , it returns the first item index found, otherwise it raises an error so it can be used as follows:
items = [1,2,3,4,5]
item_index = None
try:
item_index = items.index(3) # look for 3 in the list
except ValueError:
# do item not found logic
print("item not found") # example
else:
# do item found logic knowing item_index
print(items[item_index]) # example, prints 3
also please avoid naming variables list as it overrides the built-in function list.
If you simply want to check if the number is in the list and print it or print it's index, you could simply try this:
ls = [1,2,3]
num = 2
if num in ls:
# to print the num
print(num)
# to print the index of num
print(ls.index(num))
else:
print('Number not in the list')
animals = ['cat', 'dog', 'rabbit', 'horse']
index = animals.index('dog')
print(index)

How can I remove not a first occurrence in the list?

So I have a couple lists which look like this:
lst = [1, 3, 1, 1] and lst2 = [3]
I need to remove "1" from the lst, but a specific "1": lst[2] and I need to insert the "3" from lst2 into that particular spot.
Remove doesn`t really help, because it removes the first occurrence.
Thanks a lot!
You can use del to delete element at given index in python. To insert element at specific position, you can use in insert(index, element). In your case, following will work:
lst = [1, 3, 1, 1]
lst2 = [3]
del lst[2] #This will delete element at position 2 from lst list
lst.insert(2,3) #This will insert element 3 at position 2 in lst
lst=[int(input("Enter a number into the list: "))]
lstcopy=lst
while True:
new=input("Enter one more number into the list: ")
if not new:
break
lst.append(int(new))
findMe=int(input("Enter the number to find: "))
findMeOccurence=int(input("Enter the occurence number of "+str(findMe)+" that you want to find: "))
idx=-1
error=False
try:
for i in range(findMeOccurence):
idx+=1
lstcopy=lstcopy[idx:]
idx=lstcopy.index(findMe)
except:
print("Your number does not exist at that occurence.")
error=True
if not error:
del lst[idx+1]
print("\nThis is your list with "+str(findMe)+" removed at occurence "+str(findMeOccurence)+":\n"+str(lst))
What this does is get your list (you can preset it and remove the list getting code), make a copy of it in lstcopy, get the number to find (again you can preset), and the position to find it (presetting is possible here, too). Then it sets idx to -1 and error to False. Inside the try, a loop is done that:
Increases idx by 1
Cuts lstcopy so that the next step doesn't do this recursively
Use index to get the new idx.
index raises an exception when it cannot find the given item, and that will be caught with the except, saying that your number doesn't exist (because the loop hadn't finished yet, so the occurrence was not found). Then it sets error to True.
At the ending part, it checks for error to be False (because by default it was False and we are using the not keyword), and if so, that means the error message ("Your number does not exist at that occurence.") has not been given, so delete the index using del lst[idx+1] and show the user the new list. This is the reason lstcopy was made: because at the end, it needs the full lst to del from, not the cut up lstcopy from that loop!
I have tried this with Python 3.8.1, try it yourself and tell me in the comments if it worked!

Python - Removing first two occurrences of element in list

The objective of this function is to remove the first two occurrences of n in a list.
Below is a code I had written but I still got it wrong after many hours. A friend advised me not to edit a list while iterating. However, I'm still stuck.
def remove_first_two(list,n):
if list == []:
return []
else:
count = 0
for ele in list:
if ele == n:
list.remove(ele)
count += 1
if count == 2:
break
return list
list = [1,2,2,3]
print(remove_first_two(list,2)) => [1,2,3] instead of [1,3]
Use list.remove twice with try-except. That will delete first two entries. Complexity O(n)
list_a = [1,2,3,4]
try:
list_a.remove(n)
list_a.remove(n)
# run a loop too, if it's more than 2
except:
pass
You can try find all indexes and del:
a = [1,2,3,2,3,2,4]
indices = [i for i, x in enumerate(a) if x == 2]
print(indices)
[1, 3, 5]
del a[indices[0]], a[indices[1]]
print(a)
[1, 3, 2, 2, 4]
First, don't use 'list' as its a key word in Python. Use something else, like 'alist'.
The code below does what you want and keeps the basic form of what you already have. You can of course also use the built-in .remove() method.
def remove_first_two(alist, n):
if alist == []:
return []
else:
count = 0
while count < 2:
for ele in alist:
if ele == n:
alist.remove(ele)
count += 1
return alist
alist = [1,2,2,3]
print(remove_first_two(alist,2)) # Output -> [1,3]
When your friend says "do not edit a list while iterating," he/she is right, and what he/she means is that you should create another list all together. What you are looking to do is the following:
def remove_first_two(list, n):
if list == []:
return []
else:
new_list = []
count = 0
for ele in list:
if ele == n:
if count >= 2:
new_list.append(ele)
count += 1
else:
new_list.append(ele)
return new_list
However, note that you can use use some built in functions to make your life much easier:
list.remove(x)
Remove the first item from the list whose value is equal to x. It raises a ValueError if there is no such item.
Therefore, you can more simply do:
def remove_first_two(list, n):
if list == []:
return []
for _ in range(2):
if n in list:
list.remove(n)
return list
Python updates the list if you change it while iterating.
In you test case with list = [1,2,2,3] when list[1] is deleted and Python updates list = [1,2,3]. Now Python understands you have iterated till index 1 and continues from index 2 which now contains 3. So Python encounters only one occurance of 2.
So heed your friends advice and do not edit list while iterating :)
Now you can use Python's in-built list.remove(element) to delete first ocuurence of a element. Repeat it 2 times for desired output.
Also O(n) with a single parse.
def remove_first_two(mylist,n):
counter = 0
def myfilter (i):
nonlocal counter,n
if counter > 2:
return True
else:
counter += 1
return (i != n)
return (list(filter(myfilter,mylist)))
This can also be done in python 3.8 using assignment expressions in a list comprehension:
data = [1,2,3,2,3,2,4]
count = 2
num = 2
[x for x in data if x != num or (count:=count-1) < 0]
Results:
[1, 3, 2, 2, 4]
Here is the reason why your program does not work:
When you remove an element, the for loop moves on to the next element, but by "moving on" it is actually skipping the element which now occupies the position of the deleted element. It skips the element right after the one you deleted.
The correct way to iterate over a list while you delete elements is making index progression explicit, by using a while loop instead of a for loop, and not increase the index when you delete an element:
i = 0
while i < len(my_list):
if condition:
my_list.pop(i)
else:
i += 1
However, none of this is necessary in your case! Notice that when you use my_list.remove(ele), you are not providing an index as you would with my_list.pop(i), so Python has to search for the first element that matches ele. Although remove will be slower than pop when used by themselves, here remove allows you not use any loops at all, simply do my_list.remove(n) twice!
Last touch: If your list has less than two elements matching n, one of the two my_list.remove(n) commands would return a ValueError. You can account for this exception, knowing that if it happens, your list is ready and requires no further action.
So the code you need is:
try:
my_list.remove(n)
my_list.remove(n)
except ValueError:
pass

Python: Function to find out if a tuple contains even numbers?

So what I want is a function that gets a tuple input from a user and then figures out if that tuple contains an even number. I want to know how to do it with a for or while loop. I've tried it but the code doesn't work. I've kind of got something but it's not working:
def ifEven(x):
i = -1
if isinstance(x, tuple):
while i < len(x):
for i in x:
i = i + 1
if x[i] % 2 == 0:
return True
else:
return False
You should read the documentation about for statement in Python: https://docs.python.org/2/tutorial/controlflow.html#for-statements.
Here is a working code:
def ifEven(x):
if isinstance(x, tuple):
for i in x:
if i % 2 == 0:
return True
return False
That being said, it can be rewritten as a one-liner using Python's generator expressions:
def isEven(x):
return any(v % 2 == 0 for v in x)
You indentation looks a bit off but that might just be how you copy/pasted. True is "True" in python not "true" as in your return function which might also be messing you up.
In for loop i itself initializes and start iterating over the tuple. The content of i at each iteration is one of the element from the tuple.
Let's have a deeper look into it. let your tuple be (3, 4, 6, 7)
In first iteration :-
for i in x # i=3
i = i+1 # i = 4
if x[i] %2 == 0 : # x[4] % 2 == 0 => This will give you IndexError, since there is no index 4 in the tuple x(python uses zero based indexing)
So you don't need to increment i separately as for increments the iterating variable upto the end of the sequence provided (in your case it's upto the last element in the tuple x)
And since i posses the element from the tuple itself, so by incrementing it you are incrementing the value in i. And then you are accessing the element with incremented index from the tuple. That is, if tuple element is 3, you are first incrementing it by 1, so it becomes 4, and then you are checking whether the element in 4th index of the tuple is even or not i.e. if x[4] is even or not. But since the tuple that I have considered, is of lengthe 4, so it will throw IndexError
So, here you don't need to initialize i = -1, don't need to use while, no need to increment i inside for loop. Rest solution is given by Selcuk.

Why does Python return negative list indexes?

If I have this list with 10 elements:
>>> l = [1,2,3,4,5,6,7,8,9,0]
Why will l[10] return an IndexError, but l[-1] returns 0?
>>> l[10]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
>>> l[0]
1
>>> l[-1]
0
>>> l[-2]
9
What I want to do is throw an error if there are no previous elements in the list.
In Python, negative list indices indicate items counted from the right of the list (that is, l[-n] is shorthand for l[len(l)-n]).
If you find you need negative indices to indicate an error, then you can simply check for that case and raise the exception yourself (or handle it then and there):
index = get_some_index()
if index < 0:
raise IndexError("negative list indices are considered out of range")
do_something(l[index])
It's because l[-1] is equal to l[len(l)-1],
similarly l[-2] is equal to l[len(l)-2]
>>> lis=[1,2,3,4,5]
>>> lis[-1],lis[-2],lis[-3]
(5, 4, 3)
>>> lis[len(lis)-1],lis[len(lis)-2],lis[len(lis)-3]
(5, 4, 3)
Q: Why will l[10] return an IndexError, but l[-1] returns 0?
A: Because index values in Python (as in many other languages) are zero-based. That means the first item is stored at index 0.
Your list
l = [1,2,3,4,5,6,7,8,9,0]
has 10 items. Since the index starts at 0, the last item will be at index 9. When you try to access your list at index 10, Python rightly throws an IndexError exception to tell you that this is not a valid index value and is out of bounds.
Python also uses the convention of negative index values to access items from the "end" of a list or sequence. Index value -1 indicates the last item in the list, -2 the next-to-last etc. Since the last item in your list is 0, this is what l[-1] returns.
#Lattyware's answer already shows you how to generate/throw an exception, I hope this answers your initial question.
Because, index value starts from 0. In your case the last index value is 9, no more index value after 9. when you try print the values beyond the index value limit, it must throws an error

Categories

Resources