如何编写一个带有字符串参数并返回一个字符串的递归函数,该字符串的相邻相同字符之间用空格分隔?
我编写了一个非递归函数,该函数可以实现我想要的功能:
def space_adj(istr):
new_str = ''
delimiter = ' '
for i, ch in enumerate(istr[:len(istr)-1]):
if ch == istr[i+1]:
new_str += ch + delimiter
else:
new_str += ch
new_str += istr[-1]
return new_str
我希望它这样做:
>>> space_adj('abcdeffghhh')
'abcdef fgh h h'
答案 0 :(得分:1)
实际上不需要进行递归,但是可以这样进行:
delimiter = " "
def space_adj(istr):
if len(istr) < 2: # The end-condition for the recursion
return istr
result = space_adj(istr[:-1]) # Get result for the shorter string with recursion
if istr[-1] == istr[-2]:
return result + delimiter + istr[-1]
else:
return result + istr[-1]
请注意istr[:-1]
的较短语法istr[:len(istr)-1]
。
仅提及一种不相关的替代方法:您可以使用一个正则表达式替换来完成此操作:
import re
def space_adj(istr):
return re.sub(r"(\w)(?=\1)", r"\1 ", istr)
答案 1 :(得分:1)
您可以使用像这样的典型基数和归纳案例设计递归函数-
def space_adj (s, delim = " "):
# base case: one char or less
if len(s) < 2:
return s
# inductive case 1: at least two chars
elif s[0] == s[1]:
return s[0] + delim + space_adj(s[1:], delim)
# inductive case 2: at least two unmatching chars
else:
return s[0] + space_adj(s[1:], delim)
Python在许多基本操作中都使用了符号语法,但我认为这总体上损害了程序的可读性-
def first (x):
return x[0]
def second (x):
return x[1]
def tail (x):
return x[1:]
def space_adj (s, delim = " "):
if len(s) < 2:
return str
elif first(s) == second(s):
return first(s) + delim + space_adj(tail(s), delim)
else:
return first(s) + space_adj(tail(s), delim)
程序的每个版本的输出都是相同的-
print(space_adj("abcdeffghhh"))
# "abcdef fgh h h"
print(space_adj("a"))
# "a"
print(space_adj(""))
# ""
或尝试使用辅助功能将问题分解为更小的部分。下面我们不得不编写两个函数,而不仅仅是一个,但是每个函数都是
def join (a, b, delim = " "):
if a == b:
return a + delim
else:
return a
def space_adj (s):
if len(s) < 2:
return s
else:
return join(s[0], s[1]) + space_adj(s[1:])
print(space_adj("abcdeffghhh"))
# "abcdef fgh h h"
递归是一种功能性遗产,因此最好在其自然环境中学习递归。在上方您可以看到space_adj
只是一台简单的机器-
space_adj("abcde")
= join("a","b")
+ join("b","c")
+ join("c","d")
+ join("d","e")
+ "e"
这意味着space_adj
本身可以作为通用函数,只要我们将join
设为参数。在下面,我们为联接命名space_between_same
。现在我们有了通用的joiner
函数-
def space_between_same (a, b):
if a == b:
return a + " "
else:
return a
def joiner (s, join = space_between_same):
if len(s) < 2:
return s
else:
return join(s[0], s[1]) + joiner(s[1:], join)
print(joiner("abcdeffghhh"))
# "abcdef fgh h h"
现在我们可以指定如何进行联接,我们可以看到高阶函数的功能和灵活性-
joiner("CamelToTitleCase", lambda a, b: a + " " if b.isupper() else a)
# "Camel To Title Case"
joiner("CamelToSnakeCase", lambda a, b: a.lower() + "_" if b.isupper() else a.lower())
# "camel_to_snake_case"
joiner("reemoveed duplicatees", lambda a, b: "" if a == b else a))
# "removed duplicates"
joiner([ 1, 2, 2, 3, 3, 3 ], lambda a, b: [] if a == b else [a]))
# [ 1, 2, 3 ]
以上,space_between_same
硬编码" "
分隔符。我们可以制作另一个高阶函数between_same
以使分隔符可以由用户配置-
def between_same (delim = ""):
def join (a, b):
if a == b:
return a + delim
else:
return a
return join
def joiner (s, join = between_same(" ")):
if len(s) < 2:
return s
else:
return join(s[0], s[1]) + joiner(s[1:], join)
print(joiner("abcdeffghhh")) # default
# "abcdef fgh h h"
print(joiner("abcdeffghhh", between_same("=")))
# "abcdef=fgh=h=h"
以这种方式解决问题产生了一个截然不同的程序,但是如您所见,我们可以将程序定向到许多理想的结果,而复杂度几乎为零。
相关:上面的joiner
与fold类似但不相同。
答案 2 :(得分:0)
自从您标记了[python-3.x]这个问题以来,让我们使用Python-3-ism:
def space_adj(istr):
if not istr:
return istr
first, *second_on = istr
if not second_on:
return first
second, *_ = second_on
return first + ['', ' '][first == second] + space_adj(second_on)
这里的一个窍门是我们将参数视为序列,而不是 str 。递归时,参数变为 list ,但它仍然是一个序列,因此一切正常。