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.
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.
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 (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.
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