mcal98
mcal98

Reputation: 1

Recursively going through list and compare with a value (python)

The task is to go through a list, compare it with a value and then return the amount of times the value occurred. The comparison works and when I find the matching value I want to save it in a list. Then I want to get the length of that list. The problem is that every time i call on the function again the list resets, how do I avoid that?

    def count_occurences(values, value):
        matched_values = []
        if values:
            if values[0] == value:
                matched_values.append(values[0])
                count_occurences(values[1:], value)
            else:
                count_occurences(values[1:], value)
        else:
            return 0
        return len(matched_values)
    count_occurences([1, "one", 2, "two", "two", 3, "three", "three", "three"], "two")

In this case the expected output would be: 2.

Upvotes: 0

Views: 1172

Answers (3)

Chana
Chana

Reputation: 368

 matched_values = [] 

 def count_occurences(values, value, matched_values):
            if values:
                if values[0] == value:
                    matched_values.append(values[0])
                    count_occurences(values[1:], value, matched_values)
                else:
                    count_occurences(values[1:], value, matched_values)
            else:
                return 0
            return len(matched_values, matched_values)

 count_occurences([1, "one", 2, "two", "two", 3, "three", "three", "three"], "two", matched_values)

The list was reset at every call of the recursive function count_occurences because you recreated the list at the beginning of the function with this line: matched_values = []. This creates a new variable matched_values that points to a new location in memory and does not have access to what was found by the previous round.

Initializing this empty list before the function is called ensures that the same location in memory will be accessed every time the function runs. Every recursive call will operate on the same list, and you won't lose information.

Upvotes: 0

Simon Notley
Simon Notley

Reputation: 2136

You can solve your immediate problem by simply moving the matched_values assignment outside of the function, as shown below.

matched_values = []

def count_occurences(values, value):
    if values:
        if values[0] == value:
            matched_values.append(values[0])
            count_occurences(values[1:], value)
        else:
            count_occurences(values[1:], value)
    else:
        return 0
    return len(matched_values)
count_occurences([1, "one", 2, "two", "two", 3, "three", "three", "three"], "two")

However, this code really raises more questions than it answers. Presumably you are doing this as a learning exercise as you can easily do this without a special function or recursion. So bearing that in mind I'd ask you:

  • What is the point of matched_values? By definition it will just be the same entry repeatedly so it adds no information over just knowing the number of matches
  • Recursion is a common pattern in functional programming but your function's primary purpose is to mutate a variable outside the function - this is called a side effect and is generally considered undesireable in functional style

With those in mind, you might consider something like this which does away with the list and involves no mutation and no side effects.

def count_occurences(values, value):
    if values:
        if values[0] == value:
            return 1 + count_occurences(values[1:], value)
        else:
            return count_occurences(values[1:], value)
    else:
        return 0

(which is essentially identical to the simplification suggested by Andrej Kesely above)

Upvotes: 1

Andrej Kesely
Andrej Kesely

Reputation: 195543

As @juanpa.arrivillaga stated in comments, you are initializing matched_values to empty list each call, so you are returning nothing effectively.

The script can be simplified, for example:

def count_occurences(values, value):
    if values:
        return (values[0] == value) + count_occurences(values[1:], value)
    return 0

n = count_occurences([1, "one", 2, "two", "two", 3, "three", "three", "three"], "two")
print(n)

Prints:

2

Upvotes: 1

Related Questions