I am trying to get the count of all items in the nested lists. while the code traverse through all items, the counter gets set to only non-nested list items. what is happenning and how to I correct this code?
def countarr(arr,count):
if len(arr) == 0:
return count
else:
if type(arr[0]) != list:
count = 1
print(arr[0],count)
else:
print ("inner")
countarr(arr[0],count)
return countarr(arr[1:],count)
count=0
arr=[1,2,[[4,5]],8,[7,4,5,6],12,34]
print("Answer: ",countarr(arr, count))
CodePudding user response:
Variables don't magically reset. They only are set to the value you give it. Modifying the value of a local variable does not affect the value of another variable in another function, even if it has the same name. Take the following example:
def foo(count):
print(count)
count = 1
print(count)
def bar()
count = 0
print(count)
foo(count)
print(count)
bar()
Recursion is the same. Each recursive function call has its own copies of local variables just in the same way foo()
and bar()
each have a variable named count that are independent of each other.
To fix the recursive function, just return the value of count
from every possible if...else
branch. You already do this in two of the branches, but you only print the value in two other branches and don't return it.
CodePudding user response:
count
is a variable of type int
. When passing an int
as parameter to a function in python, only the value is passed, not the actual variable. So, when the recursive call "modifies count
", it actually modifies a copy of the variable, not the original. So, the original is not updated.
Furthermore, when you do the recursive call: countarr(arr[0])
, you're not using the return value of that call. You can simply add count =
in front of the recursive call, to retrieve the returned value of the recursive call:
def countarr0(arr,count):
if len(arr) == 0:
return count
else:
if not isinstance(arr[0], list):
count = 1
else:
count = countarr0(arr[0], count)
return countarr0(arr[1:], count)
arr=[1,2,[[4,5]],8,[7,4,5,6],12,34]
print("Answer: ",countarr0(arr, 0))
# Answer: 11
However, passing an argument count
to the recursive call is not really useful. The recursive call doesn't need to know the current value of count
. The recursive call should just count how many elements are in the nested sublist, and we'll add its return value to our current count:
def countarr1(arr):
if len(arr) == 0:
return 0
else:
count = 0
if isinstance(arr[0], list):
count = countarr1(arr[0])
else:
count = 1
count = countarr1(arr[1:])
return count
arr=[1,2,[[4,5]],8,[7,4,5,6],12,34]
print("Answer: ",countarr1(arr))
# Answer: 11
Note that using recursion to navigate the sublists is a good idea; but using recursion to iterate on the list is a bad idea in python. In python, recursion is much slower than for
-loops; in addition, when you write arr[1:]
, a whole new copy of the array is made! That's terribly inefficient. Instead, we can use a loop to iterate on the list:
def countarr2(arr):
count = 0
for x in arr:
if isinstance(x, list):
count = countarr2(x)
else:
count = 1
return count
arr=[1,2,[[4,5]],8,[7,4,5,6],12,34]
print("Answer: ",countarr2(arr))
# Answer: 11