我理解递归就是函数调用自身的时候,但我无法弄清楚如何让我的函数自我调用以获得所需的结果。我需要简单地计算赋予函数的字符串中的元音。
def recVowelCount(s):
'return the number of vowels in s using a recursive computation'
vowelcount = 0
vowels = "aEiou".lower()
if s[0] in vowels:
vowelcount += 1
else:
???
我最终想出了这一点,感谢此处的一些见解。
def recVowelCount(s):
'return the number of vowels in s using a recursive computation'
vowels = "aeiouAEIOU"
if s == "":
return 0
elif s[0] in vowels:
return 1 + recVowelCount(s[1:])
else:
return 0 + recVowelCount(s[1:])
答案 0 :(得分:6)
试试这个,这是一个简单的解决方案:
def recVowelCount(s):
if not s:
return 0
return (1 if s[0] in 'aeiouAEIOU' else 0) + recVowelCount(s[1:])
它考虑了元音是大写或小写的情况。它可能不是递归遍历字符串的最有效方法(因为每个递归调用都会创建一个新的切片字符串),但它很容易理解:
第二步最终将字符串减少到零长度,从而结束递归。或者,可以使用tail recursion实现相同的过程 - 并不是因为CPython没有实现tail recursion elimination而对性能产生任何影响。
def recVowelCount(s):
def loop(s, acc):
if not s:
return acc
return loop(s[1:], (1 if s[0] in 'aeiouAEIOU' else 0) + acc)
loop(s, 0)
只是为了好玩,如果我们删除解决方案必须递归的限制,我就是这样解决的:
def iterVowelCount(s):
vowels = frozenset('aeiouAEIOU')
return sum(1 for c in s if c in vowels)
无论如何这都有效:
recVowelCount('murcielago')
> 5
iterVowelCount('murcielago')
> 5
答案 1 :(得分:3)
您的功能可能需要看起来像这样:
答案 2 :(得分:1)
使用切片删除第一个字符并测试其他字符。您不需要else块,因为您需要为每个案例调用该函数。如果你把它放在else块中,那么当你的最后一个字符是元音时它将不会被调用: -
### Improved Code
def recVowelCount(s):
'return the number of vowels in s using a recursive computation'
vowel_count = 0
# You should also declare your `vowels` string as class variable
vowels = "aEiou".lower()
if not s:
return 0
if s[0] in vowels:
return 1 + recVowelCount(s[1:])
return recVowelCount(s[1:])
# Invoke the function
print recVowelCount("rohit") # Prints 2
这将使用带有第1个字符的新字符串调用递归函数。
答案 3 :(得分:0)
这是一种函数式编程方法供您学习:
map_ = lambda func, lst: [func(lst[0])] + map_(func, lst[1:]) if lst else []
reduce_ = lambda func, lst, init: reduce_(func, lst[1:], func(init, lst[0])) if lst else init
add = lambda x, y: int(x) + int(y)
is_vowel = lambda a: a in 'aeiou'
s = 'How razorback-jumping frogs can level six piqued gymnasts!'
num_vowels = reduce_(add, map_(is_vowel, s), 0)
这个想法是将问题分成两个步骤,其中第一个(“地图”)将数据转换为另一个形式(字母 - > 0/1),第二个(“减少”)将转换后的项目转换为一个单一的值(1的总和)。
参考文献:
另一个更高级的解决方案是将问题转换为tail recursive并使用trampoline来消除递归调用:
def count_vowels(s):
f = lambda s, n: lambda: f(s[1:], n + (s[0] in 'aeiou')) if s else n
t = f(s, 0)
while callable(t): t = t()
return t
请注意,与天真的解决方案不同,这个解决方案可以使用非常长的字符串,而不会导致“超出递归深度”错误。
答案 4 :(得分:0)
这是一种直截了当的方法:
VOWELS = 'aeiouAEIOU'
def count_vowels(s):
if not s:
return 0
elif s[0] in VOWELS:
return 1 + count_vowels(s[1:])
else:
return 0 + count_vowels(s[1:])
这里的代码相同:
def count_vowels_short(s):
if not s:
return 0
return int(s[0] in VOWELS) + count_vowels_short(s[1:])
这是另一个:
def count_vowels_tailrecursion(s, count=0):
return count if not s else count_vowels_tailrecursion(s[1:], count + int(s[0] in VOWELS))
不幸的是,对于长字符串, 会失败。
>>> medium_sized_string = str(range(1000))
>>> count_vowels(medium_sized_string)
...
RuntimeError: maximum recursion depth exceeded while calling a Python object
如果感兴趣,请查看this blog article。