Python:用于检查字符串是否为回文的递归函数

Python:用于检查字符串是否为回文的递归函数,python,python-2.7,python-3.x,Python,Python 2.7,Python 3.x,所以我试图创建一个递归函数来检查一个单词是否是回文。它应该忽略所有非字母字符。这是我到目前为止所拥有的 def is_palindrome(text): ''' A Recursive Function that returns True if the parameter, text, is a palindrome, False if not. Ignores capitalization, punctuation, and spaces. text: a S

所以我试图创建一个递归函数来检查一个单词是否是回文。它应该忽略所有非字母字符。这是我到目前为止所拥有的

def is_palindrome(text):
    '''
    A Recursive Function that returns True if the parameter, text, is a palindrome, False if not.
    Ignores capitalization, punctuation, and spaces.

    text: a String
    returns True or False
    '''
    text = list(text)
    if len(text) == 0:
        return True
    else:
        if text[0].isalpha():
            if text[-1].isalpha():
                if text[0].lower() == text[-1].lower():
                    text.remove(text[0])
                    text.remove(text[-1])
                    return is_palindrome(text)
                else:
                    return False
            else:
                text.remove(text[-1])
                return is_palindrome(text)
        else:
            text.remove(text[0])
            return is_palindrome(text)
下面是一些测试用例


是回文(“abcde”)

结果

abcde
False

结果

aabbaa
['b', 'b', 'a', 'a']
False
aa bb aa
[' ', 'b', 'b', ' ', 'a', 'a']
['b', 'b', ' ', 'a', 'a']
False

结果

aabbaa
['b', 'b', 'a', 'a']
False
aa bb aa
[' ', 'b', 'b', ' ', 'a', 'a']
['b', 'b', ' ', 'a', 'a']
False

所以出于某种原因,它总是直接以错误告终

如何解决这个问题?所有的帮助将不胜感激

text.remove(text[0])
不会执行您认为它会执行的操作(它会从列表中删除该值的第一个匹配项)。要按索引删除,请使用切片。您可以重写以下内容:

text.remove(text[0])
text.remove(text[-1])
为此:

text = text[1:-1]
text.remove(text[0])
不会执行您认为它会执行的操作(它会从列表中删除该值的第一个匹配项)。要按索引删除,请使用切片。您可以重写以下内容:

text.remove(text[0])
text.remove(text[-1])
为此:

text = text[1:-1]

这只是为了好玩,还是为了锻炼?我认为递归在这里没有什么意义:

def palindrome(s):
    l = len(s)
    m = l // 2
    return s[:m][::-1] == s[m + (l % 2):]
然后我只需对输入进行预处理,以删除非字母数字和大写字母,如:

s = 'aBc%$cbA'
palindrome(re.subn('\W', '', s)[0].lower())

这只是为了好玩,还是为了锻炼?我认为递归在这里没有什么意义:

def palindrome(s):
    l = len(s)
    m = l // 2
    return s[:m][::-1] == s[m + (l % 2):]
然后我只需对输入进行预处理,以删除非字母数字和大写字母,如:

s = 'aBc%$cbA'
palindrome(re.subn('\W', '', s)[0].lower())
从:

列表。删除(x)

从列表中删除值为x的第一项。如果没有此类项目,则为错误

当基于字符串
aabbaa
调用列表的
text.remove(text[-1])
时,列表中的第一个
a
将被删除,这并不总是所需的行为。如果要删除列表的第一个和最后一个元素,可以使用user1434070发布的切片。另一种方法是使用
list.pop(x)
删除具有指定索引的元素,方法是将对
remove
的调用替换为以下代码:

text.pop(0)
if len(text) == 0:
    return True
text.pop(-1)
请注意,如果列表包含单个字母,则必须在第一个
pop
之后检查列表的大小。当原始回文包含奇数个字符时,这会发生在递归的最深处。

来自:

列表。删除(x)

从列表中删除值为x的第一项。如果没有此类项目,则为错误

当基于字符串
aabbaa
调用列表的
text.remove(text[-1])
时,列表中的第一个
a
将被删除,这并不总是所需的行为。如果要删除列表的第一个和最后一个元素,可以使用user1434070发布的切片。另一种方法是使用
list.pop(x)
删除具有指定索引的元素,方法是将对
remove
的调用替换为以下代码:

text.pop(0)
if len(text) == 0:
    return True
text.pop(-1)
请注意,如果列表包含单个字母,则必须在第一个
pop
之后检查列表的大小。当原始回文包含奇数个字符时,这在递归的最深层发生。

list.remove()
删除
列表中第一次出现的元素。如果该元素在开头和结尾都存在,那么通过索引
列表来获取最后一个元素来选择该元素并不重要,它仍然会删除它看到的第一个元素
list.pop()
更合适,因为这样会根据元素的索引而不是值删除元素

def is_palindrome(text):
    text = list(text)
    if len(text) == 0:
        return True
    else:
        if text[0].isalpha():
            if text[-1].isalpha():
                if text[0].lower() == text[-1].lower():
                    text.pop(0)
                    text.pop()
                    return is_palindrome(text)
                else:
                    return False
            else:
                text.pop()
                return is_palindrome(text)
        else:
            text.pop(0)
            return is_palindrome(text)
但是,您可以通过在开头过滤掉任何被忽略的字符来进一步改进程序:

def is_palindrome(text):
    text = ''.join(filter(str.isalpha, text)).lower()
    if not text:
        return True
    text = list(text)
    if text[0].lower() == text[-1].lower():
        text.pop(0)
        text.pop()
        return is_palindrome(text)
    return False
进一步的优化是使用默认参数来记录字符串是否已被清除,并向递归调用发送一个切片:

def is_palindrome(text, cleaned=False):
    if not cleaned:
        text = ''.join(filter(str.isalpha, text)).lower()
    if not text:
        return True
    if text[0] != text[-1]:
        return False
    return is_palindrome(text[1:-1], 1)
list.remove()
删除
列表中第一次出现的元素。如果该元素在开头和结尾都存在,那么通过索引
列表来获取最后一个元素来选择该元素并不重要,它仍然会删除它看到的第一个元素
list.pop()
更合适,因为这样会根据元素的索引而不是值删除元素

def is_palindrome(text):
    text = list(text)
    if len(text) == 0:
        return True
    else:
        if text[0].isalpha():
            if text[-1].isalpha():
                if text[0].lower() == text[-1].lower():
                    text.pop(0)
                    text.pop()
                    return is_palindrome(text)
                else:
                    return False
            else:
                text.pop()
                return is_palindrome(text)
        else:
            text.pop(0)
            return is_palindrome(text)
但是,您可以通过在开头过滤掉任何被忽略的字符来进一步改进程序:

def is_palindrome(text):
    text = ''.join(filter(str.isalpha, text)).lower()
    if not text:
        return True
    text = list(text)
    if text[0].lower() == text[-1].lower():
        text.pop(0)
        text.pop()
        return is_palindrome(text)
    return False
进一步的优化是使用默认参数来记录字符串是否已被清除,并向递归调用发送一个切片:

def is_palindrome(text, cleaned=False):
    if not cleaned:
        text = ''.join(filter(str.isalpha, text)).lower()
    if not text:
        return True
    if text[0] != text[-1]:
        return False
    return is_palindrome(text[1:-1], 1)

打败我!我们会给出同样的回答@Help\u Python\u Pls
remove(x)
删除列表中第一个出现的元素
x
。[1,2,5]。删除(5)将导致
[1,2]
。请注意,
remove
是一个就地操作-它将直接修改原始列表,而不是修改其副本。此外,无需将变量
text
转换为列表。Python非常聪明,能够对字符串进行切片/索引:-)@AkshatMahajan因此,另一方面,切片会修改它的副本?@Help\u Python\u请不要,切片会返回一个新列表,其中只包含您要求的元素。不是一个副本(这意味着整个列表最初是被复制的)也不是修改的(这意味着这个新列表删除了它的一些元素)——但我想这只是语义。净效果是,是的,正如你所描述的。快来吧!我们会给出同样的回答@Help\u Python\u Pls
remove(x)
删除列表中第一个出现的元素
x
。[1,2,5]。删除(5)将导致
[1,2]
。请注意,
remove
是一个就地操作-它将直接修改原始列表,而不是修改其副本。此外,无需将变量
text
转换为列表。Python足够聪明,能够对字符串进行切片/索引:-)@AkshatMahajan因此,另一方面切片会修改它的副本?@Help\u Python\u请不要,切片返回