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.
Related
So, I need to use a for i in loop on a list that is within a list. Let me give you an example.
I have a blacklist (list) that contains 10 categories (also lists), in those categories, there are always 2 ints.
I also have a list called x. x contains 2 ints.
I want to check if the 2 ints inside x are the same as any of the blacklist categories.
In order to do that I need to do
def blacklist_check(blacklist, z):
for i in blacklist:
for y in blacklist[i]:
difference = blacklist[i][y] - z
if difference < 10 and difference > -10:
print(f"{difference} found")
return False
print(f"{difference} not found")
if i == 10:
return True
but when I try that I get
TypeError: list indices must be integers or slices, not list
I can not transfer the categories to ints or any other type than lists. How do I make this work?
Here (y) is a list, you cannot nest a list as a index inside another list.
Try this
def blacklist_check(blacklist, z):
for i in blacklist:
for y in range(len(i)):
difference = i[y] - z
if difference < 10 and difference > -10:
print(f"{difference} found")
return False
print(f"{difference} not found")
if i == 10:
return True
Python handles for loops differently to perhaps a more conventional C-Type language in that it runs based on enumeration rather than incrementation.
In your case, what you have with for i in blacklist, for each iteration of the for loop, i is set to the element rather than the index, so if your data structure looks something like:
[ [1,2,3,4], [5,6,7,8] ]
Then the first value of i will be [1, 2, 3, 4], and is hence a list. If you want the indexes rather than the elements, you could use the range and len functions in the following way:
for i in range(len(blacklist)):
which will make i be 0 on the first iteration, and 1 on the second one, etc.
That would mean that calling blacklist[i] will return [1, 2, 3, 4]
If you don't consider the printed statements in the sample code, the simplest way to write it should be to use any with generator expression:
def blacklist_check(blacklist, z):
return not any(abs(y - z) < 10 for cls in blacklist for y in cls)
This is equivalent to:
def blacklist_check(blacklist, z):
for cls in blacklist:
for y in cls:
if abs(y - z) < 10: # same as -10 < (y - z) < 10
return False
return True
Note that since i in your code does not represent the index of the element in the blacklist, you should not judge whether it is the last element by i == 10, but should directly return True after the end of the for loop.
I'm trying to get the minimum odd number using python. I used lambda, loops and other methods to get minimum odd number but i was not able to get that using functions. here is my code
z= [1,8,-4,-9]
def min_odd(x):
for i in x:
if (i%2!=0):
return min(i)
y = min_odd(z)
print (y)
Can some please tell me what i was missing here.
The min() function expects an iterable like a list which it will then yield the smallest element from.
E.g. min([1,0,3]) gives 0.
So if you want to use it, you must create a list (or other iterable) of the odd numbers that you can then pass into it:
def min_odd(x):
odds = []
for i in x:
if i % 2 != 0:
odds.append(i)
return min(odds)
note that we could also use a list-comprehension:
def min_odd(x):
return min([i for i in x if i % 2 != 0])
which both work.
An alternative method would be to store the current minimum odd value in a variable and update this variable if we come across a smaller odd value:
def min_odd(x):
min_v = float('inf')
for i in x:
if i % 2 != 0 and i < min_v:
min_v = i
return min_v
Try:
min([val for val in z if val % 2 != 0])
It seems your code logics are wrong. First off, you seem to have an indentation error in the return statement. Second off, the min() function requires a collection of items (like an array for example) or a series of arguments to determine the minimum in that series. You can try multiple things.
Use another variable to store a temporary minimum. Replace it every time you find a smaller odd value ( for every i in x... if the value is odd and is smaller than the previous odd value, replace it) and have it started with the first odd number you can find.
Take all the odd numbers and add them to another array on which you will apply the min function.
Hope this proves useful!
You could pass a generator into the min() function:
def min_odd(iterable):
return min(i for i in iterable if i % 2)
I didn't write i % 2 != 0 because any odd number will return 1 which has a Boolean value of True.
I added a parameter to the function that takes the iterable so it can be used for any iterable passed in.
min operates on an iterable. i is not an iterable in your code; it's the last element of the list.
You can achieve what you want with a filter, though:
min(filter(lambda e: e%2 != 0, x))
This question already has answers here:
Remove an even/odd number from an odd/even Python list
(3 answers)
Closed 6 years ago.
So I understand placing even numbers in a new list but when there are a number of odd numbers in front I can only seem to call -1? and for an empty string I receive 'nothing' when it should also return -1
def first_even(items):
""" (list of int) -> int
Return the first even number from items. Return -1 if items contains no even numbers.
>>> first_even([1, 9, 3, 77, 13, 5, 8])
8
>>> first_even([7, 1])
-1
"""
even = []
for num in items:
if num % 2 == 0:
even.append(num)
else:
return -1
return even[0]
def first_even(items):
""" (list of int) -> int
Return the first even number from items. Return -1 if items contains no even numbers.
>>> first_even([1, 9, 3, 77, 13, 5, 8])
8
>>> first_even([7, 1])
-1
"""
for num in items:
if num % 2 == 0:
return num
return -1
The else block will be executed for the first odd number, this will terminate the for and discard all previous appends. Instead you want to return the even number as soon as it is found (you don't need the list) and then move the else to align with the for or outside the for:
def first_even(items):
for num in items:
if num % 2 == 0:
return num
else:
return -1
# or put the default value to return here
Reference for Python for/else block:
How can I make sense of the `else` clause of Python loops?
As others have noted, your else case is causing premature termination, and the use of a list is rather pointless. You could fix all this, see the other answers for minimalist fixes, but there is another option: Let Python built-ins do more of the work for you.
The next function will return the first item from an iterator, and with a second argument, if the iterator is empty, it returns the second argument instead. So give it a generator expression that lazily produces all the even numbers in the input, and it will pull the first one and return it. If none are found, the default case will return -1 for you:
def first_even(items):
# x & 1 == 0 is roughly equivalent and might be slightly faster
return next((x for x in items if x % 2 == 0), -1)
For the pathological sorts, this might be slightly faster, but it's far less intuitive to people who don't already know Python internals inside and out; I don't recommend it:
from itertools import filterfalse # ifilterfalse on Py2
def first_even(items):
# (1).__rand__ is roughly equivalent, and may be faster
return next(filterfalse((2).__rmod__, items), -1)
I got a little question: I got 2 lists with equal lengths.
As you can see below in my code, if appropriate circumstances take place, I delete some of the elements from the list. I have to do my work very carefully so my question is - does the for loop check by every iteration if len(whole_st_gen) is changing ?? Won't it skip some items??
whole_st_gen = []
whole_end_gen = [] // the length of both of them is 38273
if_merge = 0
here_merge = 0
deleting = False
for x in range (0, len(whole_st_gen)):
if_merge = x
if x == len(whole_st_gen)-1:
break
for y in range (x+1, len(whole_st_gen)):
if whole_end_gen[x]>whole_end_gen[y]:
deleting = True
here_merge = y
continue
else:
break
if deleting == True:
deleting = False
del whole_st_gen[x:here_merge]
del whole_end_gen[x:here_merge]
if_merge = 0
here_merge = 0
print len(whole_st_gen) # here's length is 1852, so i think it could work properly, just want to be sure!
sys.exit()
No , when you are using range() method, it does not check the length of the array in each iteration. Especially in Python 2.x , range() returns a list , which is what you iterate over, and this list is created at the start of the loop , it does not get recalculated in each iteration. So there can be multiple issues you can run into when using above method.
One being that you can skip some elements, since if you delete an element from the list, the indices of the list are rearranged to make a contigous sequence, so you would end up missing some elements.
Secondly, you can end up getitng IndexError , Simple example of that -
>>> l = [1,2,3,4]
>>> for i in range(0,len(l)):
... del l[i]
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
IndexError: list assignment index out of range
This is because like I said in starting range() computes the complete range (even xrange() in Python 2.x) at the start itself. This does not happen for you because of -
if x == len(whole_st_gen)-1:
break
Like said in the comments an easier way for you to go would be to use while loop , which does not increment when deleting the item. Example -
if_merge = 0
here_merge = 0
deleting = False
x = 0
while x < len(whole_st_gen):
for y in range (x+1, len(whole_st_gen)):
if whole_end_gen[x]>whole_end_gen[y]:
deleting = True
here_merge = y
else:
break
if deleting == True:
deleting = False
del whole_st_gen[x:here_merge]
del whole_end_gen[x:here_merge]
else:
x += 1
here_merge = 0
print len(whole_st_gen)
sys.exit()
In the for statement the expression list (after the in) is evaluated first to get an iterator (or iterable) which is then used for the iteration, the expression list is not evaluated again in each iteration.
In your case you call the range function to retrieve an iterator (in python3) or iterable (in python2 in the form of a list). In both cases the iterator/iterable will yield len(whole_st_gen) (as it evaluates when you reach the for statement from above) numbers (ranging from zero). If you alter the whole_st_len in the loop it will not affect the iterator and it will yield the same numbers anyway (leading to you skipping numbers, and eventually get numbers that are beyond the indices for whole_st_gen).
As opposed to the situation where you iterate over the container itself the behaviour when you do this is fully specified. You may delete and insert elements in the container if you are careful.
Here is a straight answer to your question, you should not delete items on a list while iterating on the same list, it yields unexpected results to you as some items will be skipped. Inorder to avoid this you can use copy of same list in the iteration.
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]))