简体   繁体   English

使用递归计算字符串中给定字符的出现次数

[英]Count occurrences of a given character in a string using recursion

I have to make a function called countLetterString(char, str) where I need to use recursion to find the amount of times the given character appears in the string.我必须创建一个名为countLetterString(char, str)的函数,我需要在其中使用递归来查找给定字符在字符串中出现的次数。

My code so far looks like this.到目前为止,我的代码看起来像这样。

def countLetterString(char, str):
    if not str:
        return 0
    else:
        return 1 + countLetterString(char, str[1:])

All this does is count how many characters are in the string but I can't seem to figure out how to split the string then see whether the character is the character split.所有这一切都是计算字符串中有多少个字符,但我似乎无法弄清楚如何拆分字符串然后查看字符是否是字符拆分。

The first step is to break this problem into pieces:第一步是将这个问题分解为多个部分:

1. How do I determine if a character is in a string? 1.如何判断一个字符是否在字符串中?

If you are doing this recursively you need to check if the first character of the string.如果您以递归方式执行此操作,则需要检查字符串的第一个字符是否。

2. How do I compare two characters? 2. 如何比较两个字符?

Python has a == operator that determines whether or not two things are equivalent Python 有一个==运算符,用于确定两件事是否等价

3. What do I do after I know whether or not the first character of the string matches or not? 3. 知道字符串的第一个字符是否匹配后怎么办?

You need to move on to the remainder of the string, yet somehow maintain a count of the characters you have seen so far.您需要继续处理字符串的其余部分,但要以某种方式保持您迄今为止看到的字符的计数。 This is normally very easy with a for-loop because you can just declare a variable outside of it, but recursively you have to pass the state of the program to each new function call.这通常使用 for 循环非常容易,因为您可以在其外部声明一个变量,但您必须递归地将程序的状态传递给每个新的函数调用。

Here is an example where I compute the length of a string recursively:这是一个递归计算字符串长度的示例:

def length(s): 
   if not s:  # test if there are no more characters in the string
      return 0
   else:  # maintain a count by adding 1 each time you return
          # get all but the first character using a slice
      return 1 + length( s[1:] )

from this example, see if you can complete your problem.从这个例子中,看看你是否可以完成你的问题。 Yours will have a single additional step.您将有一个额外的步骤。

4. When do I stop recursing? 4. 什么时候停止递归?

This is always a question when dealing with recursion, when do I need to stop recalling myself.在处理递归时,这始终是一个问题,我什么时候需要停止回忆自己。 See if you can figure this one out.看看你能不能解决这个问题。

EDIT :编辑

not s will test if s is empty, because in Python the empty string "" evaluates to False ; not s将测试 s 是否为空,因为在 Python 中,空字符串""的计算结果为False and not False == Truenot False == True

First of all, you shouldn't use str as a variable name as it will mask the built-in str type.首先,你不应该使用str作为变量名,因为它会掩盖内置的 str 类型。 Use something like s or text instead.改用stext之类的东西。

The if str == 0: line will not do what you expect, the correct way to check if a string is empty is with if not str: or if len(str) == 0: (the first method is preferred). if str == 0:行不会像您期望的那样,检查字符串是否为空的正确方法是使用if not str:if len(str) == 0: (首选第一种方法)。 See this answer for more info.有关更多信息,请参阅此答案

So now you have the base case of the recursion figured out, so what is the "step".所以现在你已经弄清楚了递归的基本情况,那么“步骤”是什么。 You will either want to return 1 + countLetterString(...) or 0 + countLetterString(...) where you are calling countLetterString() with one less character.您将要返回1 + countLetterString(...)0 + countLetterString(...) ,在其中调用countLetterString()时少一个字符。 You will use the 1 if the character you remove matches char , or 0 otherwise.如果您删除的字符匹配char ,您将使用1 ,否则使用0 For example you could check to see if the first character from s matches char using s[0] == char .例如,您可以使用s[0] == char检查s中的第一个字符是否与char匹配。

To remove a single character in the string you can use slicing, so for the string s you can get all characters but the first using s[1:] , or all characters but the last using s[:-1] .要删除字符串中的单个字符,您可以使用切片,因此对于字符串s ,您可以使用s[1:]获取除第一个字符之外的所有字符,或者使用s[:-1]获取除最后一个字符之外的所有字符。 Hope that is enough to get you started!希望这足以让你开始!

Reasoning about recursion requires breaking the problem into "regular" and "special" cases.关于递归的推理需要将问题分解为“常规”和“特殊”情况。 What are the special cases here?这里有哪些特殊情况? Well, if the string is empty, then char certainly isn't in the string.好吧,如果字符串为空,那么char肯定不在字符串中。 Return 0 in that case.在这种情况下返回 0。

Are there other special cases?还有其他特殊情况吗? Not really!并不真地! If the string isn't empty, you can break it into its first character ( the_string[0] ) and all the rest ( the_string[1:] ).如果字符串不为空,您可以将其分解为第一个字符 ( the_string[0] ) 和所有其余字符 ( the_string[1:] )。 Then you can recursively count the number of character occurrences in the rest, and add 1 if the first character equals the char you're looking for.然后您可以递归计算其余字符出现的次数,如果第一个字符等于您要查找的char ,则加 1。

I assume this is an assignment, so I won't write the code for you.我假设这是一个作业,所以我不会为你编写代码。 It's not hard.这并不难。 Note that your if str == 0: won't work: that's testing whether str is the integer 0 .请注意,您的if str == 0:将不起作用:这是在测试str是否为整数0 if len(str) == 0: is a way that will work, and if str == "": is another. if len(str) == 0:是一种可行的方式,而if str == "":是另一种方式。 There are shorter ways, but at this point those are probably clearest.有更短的方法,但在这一点上,这些可能是最清楚的。

First of all you I would suggest not using char or str.首先,我建议不要使用 char 或 str。 Str is a built function/type and while I don't believe char would give you any problems, it's a reserved word in many other languages. Str 是一个内置函数/类型,虽然我不相信 char 会给你带来任何问题,但它是许多其他语言中的保留字。 Second you can achieve the same functionality using count, as in :其次,您可以使用 count 实现相同的功能,如下所示:

letterstring="This is a string!"
letterstring.count("i")

which would give you the number of occurrences of i in the given string, in this case 3.这将为您提供给定字符串中 i 的出现次数,在本例中为 3。

If you need to do it purely for speculation, the thing to remember with recursion is carrying some condition or counter over which each call and placing some kind of conditional within the code that will change it.如果您需要纯粹为了推测而这样做,那么递归要记住的事情是携带一些条件或计数器,每次调用都会在这些条件或计数器上放置某种条件来改变它。 For example:例如:

def  countToZero(count):
   print(str(count))
   if count > 0:
      countToZero(count-1)

Keep it mind this is a very quick example, but as you can see on each call I print the current value and then the function calls itself again while decrementing the count.请记住,这是一个非常简单的示例,但正如您在每次调用中看到的那样,我打印当前值,然后函数在递减计数的同时再次调用自身。 Once the count is no longer greater than 0 the function will end.一旦计数不再大于 0,函数将结束。

Knowing this you will want to keep track of you count, the index you are comparing in the string, the character you are searching for, and the string itself given your example.知道这一点后,您将需要跟踪您的计数、您在字符串中比较的索引、您正在搜索的字符以及给出示例的字符串本身。 Without doing the code for you, I think that should at least give you a start.如果不为您编写代码,我认为这至少应该给您一个开始。

You have to decide a base case first.你必须先决定一个基本情况。 The point where the recursion unwinds and returns.递归展开和返回的点。

In this case the the base case would be the point where there are no (further) instances of a particular character, say X , in the string.在这种情况下,基本情况将是字符串中没有特定字符(例如X )的(更多)实例的点。 ( if string.find(X) == -1: return count ) and the function makes no further calls to itself and returns with the number of instances it found, while trusting its previous caller information. ( if string.find(X) == -1: return count ) 并且该函数不再对自身进行调用并返回它找到的实例数,同时信任其先前的调用者信息。

Recursion means a function calling itself from within, therefore creating a stack(at least in Python) of calls and every call is an individual and has a specified purpose with no knowledge whatsoever of what happened before it was called, unless provided, to which it adds its own result and returns(not strictly speaking).递归意味着一个函数从内部调用自己,因此创建一个调用堆栈(至少在 Python 中),并且每个调用都是一个单独的并且具有特定目的,不知道在调用它之前发生了什么,除非提供它添加自己的结果并返回(严格来说不是)。 And this information has to be supplied by its invoker, its parent, or can be done using global variables which is not advisable.并且此信息必须由其调用者、其父级提供,或者可以使用不建议的全局变量来完成。

So in this case that information is how many instances of that particular character were found by the parent function in the first fraction of the string.因此,在这种情况下,信息是父函数在字符串的第一部分中找到了多少个该特定字符的实例。 The initial function call, made by us, also needs to be supplied that information, since we are the root of all function calls and have no idea(as we haven't treaded the string) of how many X s are there we can safely tell the initial call that since I haven't gone through the string and haven't found any or zero/ 0 X therefore here's the string entire string and could you please tread the rest of it and find out how many X are in there.我们进行的初始函数调用也需要提供该信息,因为我们是所有函数调用的根源,并且不知道(因为我们没有踩过字符串)我们可以安全地有多少X告诉最初的电话,因为我没有通过字符串并且没有找到任何或零/ 0 X ,因此这是整个字符串的字符串,请您踩一下其余部分find其中有多少X This 0 as a convenience could be the default argument of the function, or you have to supply the 0 every time you make the call.为方便起见,这个0可以是函数的默认参数,或者每次调用都必须提供0

When will the function call another function?该函数何时会调用另一个函数?

Recursion is breaking down the task into the most granular level(strictly speaking, maybe) and leave the rest to the (grand)child(ren).递归正在将任务分解为最细粒度的级别(严格来说,也许是),并将其余的留给(孙)子(人)。 The most granular break down of this task would be find ing a single instance of X and passing the rest of the string from the point , exclusive(point + 1 ) at which it occurred to the next call, and adding 1 to the count which its parent function supplied it with.这个任务的最细粒度的分解是find X的单个实例,并将字符串的其余部分从它发生的、排他(点+ 1 )传递到下一次调用,并将count1它的父函数为其提供了。

if not string.find(X) == -1:
    string = string[string.find(X) + 1:]
    return countLetterString(char, string, count = count + 1)`

Counting X in file through iteration/loop.通过迭代/循环计算文件中的X

It would involve open ing the file( TextFILE ), then text = read(TextFile) ing it, text is a str ing.这将涉及open文件( TextFILE ),然后text = read(TextFile)对其进行操作, text是一个str Then looping over each character ( for char in text: ) , remember granularity, and each time char (equals) == X , increment count by +=1 .然后遍历每个字符( for char in text: ),记住粒度,每次char (equals) == Xcount增加+=1 Before you run the loop specify that you never went through the string and therefore your count for the number X (in text ) was = 0 .在运行循环之前,请指定从未遍历过string ,因此您对数字X (在text中)的count= 0 (Sounds familiar?) (听起来很熟悉?)

return count . return count

#This function will print the count using recursion.
def countrec(s, c, cnt = 0):
    if len(s) == 0:
        print(cnt)
        return 0
    if s[-1] == c:
        countrec(s[0:-1], c, cnt+1)
    else:
        countrec(s[0:-1], c, cnt)

#Function call
countrec('foobar', 'o')

With an extra parameter, the same function can be implemented.使用额外的参数,可以实现相同的功能。 Woking function code:沃金功能代码:

def countLetterString(char, str, count = 0):
    if len(str) == 0:
        return count
    if str[-1] == char:
        return countLetterString(char, str[0:-1], count+1)
    else:
        return countLetterString(char, str[0:-1], count)

The below function signature accepts 1 more parameter - count .下面的函数签名接受另外 1 个参数 - count

(PS : I was presented this question where the function signature was pre-defined; just had to complete the logic.) (PS:我被提出了这个问题,其中函数签名是预定义的;只需要完成逻辑。)

Hereby, the code :特此,代码:

def count_occurrences(s, substr, count=0):
    ''' s - indicates the string,
        output : Returns the count of occurrences of substr found in s
    '''
    
    len_s = len(s)
    len_substr = len(substr)

    if len_s == 0:
        return count

    if len_s < len_substr:
        return count
    
    if substr == s[0:len_substr]:
        count += 1

    count = count_occurrences(s[1:], substr, count)       ## RECURSIVE CALL

    return count

output behavior :输出行为:

count_occurences("hishiihisha", "hi", 0) => 3 count_occurences("hishiihisha", "hi", 0) => 3

count_occurences("xxAbx", "xx") => 1 (not mandatory to pass the count , since it's a positional arg.) count_occurences("xxAbx", "xx") => 1 (不是强制传递count ,因为它是一个位置参数。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM