How to keep count in a recursive function?

后端 未结 11 780
甜味超标
甜味超标 2020-12-30 00:16

I wrote a recursive function to find the number of instances of a substring in the parent string.

The way I am keeping count is by declaring/initialising count

相关标签:
11条回答
  • 2020-12-30 01:07

    Not untested ...

    code:

    def countSubStringMatchRecursive(target, key, count=0):
        #### index = find(target, key) # HUH?
        index = target.find(key)
        if index >= 0:
            count += 1
            target = target[index+len(key):]
            count = countSubStringMatchRecursive(target, key, count)
        return count
    
    for test in ['', 'bar', 'foo', 'foofoo', 'foo foo foo fo']:
       print countSubStringMatchRecursive(test, 'foo'), test.count(key), repr(test)
    

    output:

    0 0 ''
    0 0 'bar'
    1 1 'foo'
    2 2 'foofoo'
    3 3 'foo foo foo fo'
    

    I'm presuming that this is just amusement or homework ... recursive function must be slower than corresponding Python iterative solution, which will be naturally slower than using target.count(key) ... so I haven't bothered with fixing all the problems your version had ... but do read PEP-008 :-)

    Comments on string module

    You commented that you had omitted from string import find. What version of Python are you using? What is the last update date on the book or tutorial that you are using?

    From the start of the string module (it will be on your computer as <your Python install directory>/Lib/string.py; I'm quoting from the 2.6 version):

    """A collection of string operations (most are no longer used).

    Warning: most of the code you see here isn't normally used nowadays. Beginning with Python 1.6, many of these functions are implemented as methods on the standard string object. They used to be implemented by a built-in module called strop, but strop is now obsolete itself.

    etc """

    and here is that file's code for the find function (stripped of comments):

    def find(s, *args):
        return s.find(*args)
    

    so using string.find(target, key) instead of target.find(key) is a waste.

    0 讨论(0)
  • 2020-12-30 01:08
    steps = 0
    def addPersistence(number, steps):
        steps += 1
        if len(str(number))==1:
            print(str(number) + "\nDone---------------------------------------------------")
            print("TOTAL STEPS " + str(steps-1))
    
        digits = [int(i) for i in str(number)]
    
        result = 0
        for j in digits:
            result += j
    
    
        if len(str(number)) != 1:
            print(number)
            addPersistence(result, steps)
    

    This is a example copied from one of my projects. This function is to determine to addition persistence of a number (which is adding the digits of a number and repeating it until the number gets to 1) but it surely can be reusable and you can use your function like this (This is Python 3 code, if you want to change it to Python 2, it will still work):

    count=0
    def countSubStringMatchRecursive(target,key,count):
        index=find(target,key)
        targetstring=target
        if index>=0:
            count+=1
            target=target[index+len(key):]
            countSubStringMatchRecursive(target,key,count)
        else :
            pass
        print("STEPS: "+str(count))
    

    You might notice my code and that code are a little bit different. Why? The answer is that the number of steps it takes for a number to get to 1 using that function is that the last call isn't included in my function because it's a duplication of the call before that.

    0 讨论(0)
  • 2020-12-30 01:09

    Your recursive function has O(n^2) performance because it copies the remaining contents of the string each time it finds a match. This is slower than the iterative solution O(n) and unnecessarily so.

    You can easily rewrite it to be faster, and at the same time simplify the code and extend its functionality by passing a start index for the search as an optional parameter to the function:

    def countSubStringMatchRecursive(target, key, start_index = 0):
        index = target.find(key, start_index)
        if index >= 0:
            return countSubStringMatchRecursive(target, key, index + len(key)) + 1
        return 0
    
    target_string = 'an apple and a banana'
    key = 'an'
    count = countSubStringMatchRecursive(target_string,  key)
    print "Number of instances of %r in %r is %d" % (key, target_string, count)
    

    Output:

    Number of instances of 'an' in 'an apple and a banana' is 4
    

    Update: If you really want to use the string module's find function, you can do this just by changing one line:

    index = find(target, key, start_index)
    
    0 讨论(0)
  • 2020-12-30 01:09

    Just a side note: all solutions presented (from the original Q to all the As) are solving a problem that's different than the specifically stated one (I imagine that's a bug in the specific problem statement, but, worth fixing if so;-). Consider:

    >>> 'banana'.count('ana')
    1
    >>> sum('banana'[x:x+3]=='ana' for x in range(len('banana')))
    2
    

    the first expression is counting the non-overlapping occurrences of 'ana' in 'banana'; the second one is counting all occurrences -- there are two occurrences in all, at indices 1 and 3 in 'banana', and they overlap. So given the problem statement, and I quote:

    find the no. of instances of a substring in the parent string.

    without any mention of "non-overlapping", it seems that overlapping occurrences should be counted. Of course, that's easy to fix, once noticed -- you just have to advance by 1 each time, instead of advancing by len(key) which leads you to skip overlapping occurrences.

    So, for example:

    import string
    
    def countit(target, key, startfrom=0):
        where = string.find(target, key, startfrom)
        if where < 0: return 0
        return 1 + countit(target, key, where+1)
    
    print countit('banana', 'ana')
    

    prints 2, counting both (overlapping) occurrences.

    0 讨论(0)
  • 2020-12-30 01:09

    I'm doing this course on OpenCourseware, it's great. Anyways, this is what I did. I took inspiration from adamse above.

    def countSubStringMatchRecursive(target, key, counter = 0):
        if find(target,key) == 0:
            countSubStringMatchRecursive(target[1:], key, counter + 1)
        elif find(target,key) > 0:
            countSubStringMatchRecursive(target[1:], key, counter)
        elif find(target,key) == -1:
            print counter
    
    0 讨论(0)
提交回复
热议问题