Which item in list - Python - 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)

Related

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

If else fill variable if empty list

I have lists that are empty and filled in the data. I am trying to the store last element of the list into a variable. If there are elements in the list, it is working fine. However, when I pass in a empty [] list, I get error like: IndexError: list index out of range. Which syntax I should be using for []?
ids = [
'abc123',
'ab233',
'23231ad',
'a23r2d23'
]
ids = []
# I tried these for empty
final = [ids if [] else ids[-1]] #error
# final = [ids if ids == None else ids == ids[-1]] # error
# final = [ids if ids == [] else ids == ids[-1]] # gives [[]] instead of []
print(final)
Basically, if an empty list is in ids, I need it to give []. If there are elements, then give the last element, which is working.
Here is one way to do this:
final = ids[-1] if ids else None
(Replace None with the value you'd like final to take when the list is empty.)
you can check for a empty list by below expression.
data = []
if data: #this returns False for empty list
print("list is empty")
else:
print("list has elements")
so what you can do is.
final = data[-1] if data else []
print(final)
final = ids[-1] if len(ids) > 0 else []
This will handle the immediate problem. Please work through class materials or tutorials a little more for individual techniques. For instance, your phrase ids if [] doesnt' do what you (currently) seem to think: it does not check ids against the empty list -- all it does is to see whether that empty list is "truthy", and an empty list evaluates to False.
You are getting the error because you wont be able to select the last item if the list is empty and it will rightfully throw an IndexError.
Try this example
ids = [[i for i in range(10)] for x in range(3)]
ids.append([])
last_if_not_empty = [i[-1] for i in ids if i]
Here you filter out the non-empty list by if i which is the condition to select not empty lists. From there you can pick out the last elements of the lists.
a = list[-1] if not len(list)==0 else 0

Return index of a list if condition is true using any() method in python

a = [['df','37s',''],['4d','34','jd']]
for lst in a:
if any(i=='' for i in lst):
print(lst.index(i)) # NameError: name 'i' is not defined
The code above is indicative of what I want to do.
Is it possible to get the index of the i of lst that returned true in the any() method, without using an explicit for loop over lst, and if so how?
You're merely confusing the scope of your subscript variable. Try a more direct approach with the index method:
a = [['df','37s',''],['4d','34','jd']]
target = ''
for lst in a:
if target in lst:
print(lst.index(target))
Output:
2
Now that you've altered your problem description (note that sample output really helps), try this list comprehension:
print([pos for pos, lst in enumerate(a) if target in lst])
Output:
[0]
which indicates that a[0] is the only element that contains an empty string.
If I extend the input test to
a = [['df','37s',''],
['4d','34','jd'],
['one','','more', 'try']]
The output is
[0, 2]
To answer strictly the initial question: is it possible to get the indice that returned true in the any(), without making an explicit for.
Well, it is possible. But that does not mean that you should do it. Please do not use this code in production, it relies on Cpython implementation details. Use Prune's answer instead.
a = [['df','37s',''],['4d','34','jd']]
for lst in a:
gen = (value == '' for i, value in enumerate(lst))
if any(gen):
i = gen.gi_frame.f_locals['i']
print('i=',i)
#i= 2

recursively remove adjacent duplicates in a list

I looked up and found a close example, but the answer found in this link: Remove adjacent duplicate elements from a list won't run the test cases for this problem. So this is all I have so far:
def remove_dups(thelist):
"""Returns: a COPY of thelist with adjacent duplicates removed.
Example: for thelist = [1,2,2,3,3,3,4,5,1,1,1],
the answer is [1,2,3,4,5,1]
Precondition: thelist is a list of ints"""
i = 1
if len(thelist) == 0:
return []
elif len(thelist) == 1:
return thelist
elif thelist[i] == thelist[i-1]:
del thelist[i]
return remove_dups(thelist[i:])
def test_remove_dups():
assert_equals([], remove_dups([]))
assert_equals([3], remove_dups([3,3]))
assert_equals([4], remove_dups([4]))
assert_equals([5], remove_dups([5, 5]))
assert_equals([1,2,3,4,5,1], remove_dups([1,2,2,3,3,3,4,5,1,1,1]))
# test for whether the code is really returning a copy of the original list
mylist = [3]
assert_equals(False, mylist is remove_dups(mylist))
EDIT while I do understand that the accepted answer linked above using itertools.groupby would work, I think it wouldn't teach me what's wrong with my code & and would defeat the purpose of the exercise if I imported grouby from itertools.
from itertools import groupby
def remove_dups(lst):
return [k for k,items in groupby(lst)]
If you really want a recursive solution, I would suggest something like
def remove_dups(lst):
if lst:
firstval = lst[0]
# find lowest index of val != firstval
for index, value in enumerate(lst):
if value != firstval:
return [firstval] + remove_dups(lst[index:])
# no such value found
return [firstval]
else:
# empty list
return []
Your assertion fails, because in
return thelist
you are returning the same list, and not a copy as specified in the comments.
Try:
return thelist[:]
When using recursion with list it is most of the time a problem of returning a sub-list or part of that list. Which makes the termination case testing for an empty list. And then you have the two cases:
The current value is different from the last one we saw so we want to keep it
The current value is the same as the last one we saw so we discard it and keep iterating on the "rest" of the values.
Which translate in this code:
l = [1,2,2,3,3,3,4,5,1,1,1]
def dedup(values, uniq):
# The list of values is empty our work here is done
if not values:
return uniq
# We add a value in 'uniq' for two reasons:
# 1/ it is empty and we need to start somewhere
# 2/ it is different from the last value that was added
if not uniq or values[0] != uniq[-1]:
uniq.append(values.pop(0))
return dedup(values, uniq)
# We just added the exact same value so we remove it from 'values' and
# move to the next iteration
return dedup(values[1:], uniq)
print dedup(l, []) # output: [1, 2, 3, 4, 5, 1]
problem is with your return statement,
you are returning
return remove_dups(thelist[i:])
output will be always last n single element of list
like for above soon,
print remove_dups([1,2,2,3,3,3,4,5,1,1,1])
>>> [1] #as your desired is [1,2,3,4,5,1]
which returns finally a list of single element as it don't consider Oth element.
here is recursive solution.
def remove_dups(lst):
if len(lst)>1:
if lst[0] != lst[1]:
return [lst[0]] + remove_dups(lst[1:])
del lst[1]
return remove_dups(lst)
else:
return lst

How to check if end of list was reached?

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]))

Categories

Resources