Reputation: 19
I am having trouble wrapping my head around the concept of recursion. Can someone help critique my code? I am trying to return the number of items in a list with an even number of digits recursively.
alist = ["hello", "is", "there", "anybody", "out", "there?"]
def evenItems(alist):
if len(alist[0]) == 0:
return 0
if len(alist[0]) % 2 == 0:
return evenItems(alist[1:len(alist)-1] + 1 )
else:
return evenItems(alist[1:len(alist)-1])
Upvotes: 0
Views: 287
Reputation: 692
alist = ["hello", "is", "there", "anybody", "out", "there?"]
def evenItems(alist):
if len(alist[0]) == 0: # The base case is when alist is empty. So use 'alist' instead of 'alist[0]' (alist[0] is the first element)
return 0
if len(alist[0]) % 2 == 0:
# A few things here:
# - the '+1' should be on the outside of the parenthesis because it should not be part of the recursive evenItems function call
# - To get the rest of the list you could use alist[1:] (which is from index one to the end of the list)
return evenItems(alist[1:len(alist)-1] + 1 )
else:
return evenItems(alist[1:len(alist)-1])
I like to make different variables so that I can clearly see what I am dealing with. You see I use (currentWord and restOfList). For recursive function I also like to separate the program into Base Case and Recursive call (again, just for more clarity).
alist = ["hello", "is", "there", "anybody", "out", "there?"]
def evenItems(alist):
# Base Case: If alist is empty
if len(alist) == 0:
return 0
# Recursive call
currentWord = alist[0]
restOfList = alist[1:]
if len(currentWord) % 2 == 0:
return evenItems(restOfList) + 1
else:
return evenItems(restOfList)
print(evenItems(alist))
Recursion is difficult. I usually like to print out what happens at each call so I can understand it better.
alist = ["hello", "is", "there", "anybody", "out", "there?"]
def evenItems(alist, level):
print(" " * level + "Enter evenItems. Level: " + str(level))
# Base Case: If alist is empty
if len(alist) == 0:
print(" " * level + "Exit evenItems list empty. Level: " + str(level))
return 0
# Recursive call
currentWord = alist[0]
print(" " * level + "Current Word is: " + currentWord)
restOfList = alist[1:]
print(" " * level + "Rest of List is: " + str(restOfList))
currentEvenItemsCount = 0
if len(currentWord) % 2 == 0:
currentEvenItemsCount = evenItems(restOfList, level + 1) + 1
else:
currentEvenItemsCount = evenItems(restOfList, level + 1)
print(" " * level + "Exit evenItems even word. Level: " + str(level))
return currentEvenItemsCount
print(evenItems(alist, 0))
output
Enter evenItems. Level: 0
Current Word is: hello
Rest of List is: ['is', 'there', 'anybody', 'out', 'there?']
Enter evenItems. Level: 1
Current Word is: is
Rest of List is: ['there', 'anybody', 'out', 'there?']
Enter evenItems. Level: 2
Current Word is: there
Rest of List is: ['anybody', 'out', 'there?']
Enter evenItems. Level: 3
Current Word is: anybody
Rest of List is: ['out', 'there?']
Enter evenItems. Level: 4
Current Word is: out
Rest of List is: ['there?']
Enter evenItems. Level: 5
Current Word is: there?
Rest of List is: []
Enter evenItems. Level: 6
Exit evenItems list empty. Level: 6
Exit evenItems even word. Level: 5
Exit evenItems even word. Level: 4
Exit evenItems even word. Level: 3
Exit evenItems even word. Level: 2
Exit evenItems even word. Level: 1
Exit evenItems even word. Level: 0
2
Upvotes: 1
Reputation: 22472
You could consider instead performing your check at the back of the list using negative indexing to get the last element and the sub list excluding the last element for the next recursive call:
def numEvenItems(alist):
if len(alist) == 0:
return 0
return (1 if len(alist[-1]) % 2 == 0 else 0) + numEvenItems(alist[:-1])
lst = ["hello", "is", "there", "anybody", "out", "there?"]
print(numEvenItems(lst))
Output:
2
Try it here.
Upvotes: 0