"pre-checking"列表执行双重递归时避免添加 None 类型或空字符串的首选方法吗?



我正在在python3中的列表上进行一些递归练习,并遇到了一个问题,我将返回的列表填充一些不愿意的非类型。

此特定练习是为了创建一个删除列表中所有元音字符串的函数。输入列表中的所有元素都是长度1的字符串,但该列表也可以包含更多列表。

def without_vowels(arg):
    vowels = "aeiuoåäöAEIUOÅÄÖ"
    if not arg:
        return arg
    elif isinstance(arg, str):
        if not arg in vowels:
            return arg
        else:
            return ""
    elif isinstance(arg, list):
        if without_vowels(arg[0]) == "":
            return without_vowels(arg[1:])
        else:
            return [without_vowels(arg[0])] + without_vowels(arg[1:])

预期输出:

>>> test = ["a", ["h", "e", "j"], ["t", "e", "s", "c", "o"]]
>>> without_vowels(test)
>>> [['h', 'j'], ['t', 's', 'c']]

最初,要在检测到时"删除"元音,我根本不会返回任何东西。这导致不类型添加到列表中。

输出没有工作障碍(第10,11、14-16行):

>>> without_vowels(test)
>>> [None, ['h', None, 'j'], ['t', None, 's', 'c', None]]

要解决此问题,我更改了代码以在发现位置的元音时返回一个空字符串,并在再次致电函数继续之前添加了"预检查",基本上只是检查功能调用是否会找到元音(并返回"),在这种情况下,跳过列表参数的下一部分。

我觉得我缺少一些明显的东西,并且应该有一个更好的解决方案而不使用这样的工作。

谢谢

编辑:此特定练习旨在通过双重递归解决,而不是迭代和单一递归的组合

这种特殊的练习是用双递归解决的, 与迭代和单一递归的结合

我的递归方法是保持简单,让递归为您完成工作:

VOWELS = set("aeiuoåäöAEIUOÅÄÖ")
def without_vowels(argument):
    if not argument:
        return argument
    head, *tail = argument
    if isinstance(head, list):
        head = without_vowels(head)
    elif head in VOWELS:
        return without_vowels(tail)
    return [head, *without_vowels(tail)]

用法

>>> test = ["a", ["h", "e", "j"], ["t", "e", "s", "c", "o"]]
>>> without_vowels(test)
[['h', 'j'], ['t', 's', 'c']]
>>> 

这取决于您想要的"更好解决方案"。我认为的直接方法是将元音从遇到的任何事物中删除,并在序列的元素上反复出现。我对此迈出了一步:

def without_vowels(arg):
    vowels = "aeiuoåäöAEIUOÅÄÖ"
    if not isinstance(arg, list):
        return arg
    result = [c for c in arg if not isinstance(c, str) or c not in vowels]
    for idx, c in enumerate(result):
        if isinstance(arg, list):
            result[idx] = without_vowels(result[idx])
    return result
test = ["a", ["h", "e", "j"], ["t", "e", "s", "c", "o"]]
print( without_vowels(test) )

输出:

[['h', 'j'], ['t', 's', 'c']]

我不知道它比您的(尚未更干净),但是它确实避免了直接插入然后删除空元素。

我试图在单个列表上进行概述,但我太累了,无法使它起作用。

这是我解决您问题的解决方案:

def without_vowels(arg):
    vowels = "aeiuoåäöAEIUOÅÄÖ"
    returnList = []
    for entry in arg:
        if type(entry) == str and entry not in vowels:
            returnList.append(entry)
        elif type(entry) == list:
            returnList.append(without_vowels(entry))
    return returnList
test = ["a", ["h", "e", "j"], ["t", "e", "s", "c", "o"]]
print(without_vowels(test))

和上述代码的输出:

>>> without_vowels(test)
[['h', 'j'], ['t', 's', 'c']]

编辑:我想我的解决方案会回馈空列表,如果列表中的唯一条目是元音,但是如果没关系,那么这应该可以完成工作。

我认为以下实现使您的问题没有:

VOWELS = set("aeiuoåäöAEIUOÅÄÖ")
def without_vowels(arg):
    if isinstance(arg, list):
        return [without_vowels(item) for item in arg if without_vowels(item)]
    elif isinstance(arg, str):
        non_vowels = [ch for ch in arg if ch not in VOWELS]
        if len(non_vowels) > 2:
            return non_vowels
        elif len(non_vowels) == 1:
            return non_vowels[0]
        return non_vowels
test = ["a", ["h", "e", "j"], ["t", "e", "s", "c", "o"]]
print(without_vowels(test))  # -> [['h', 'j'], ['t', 's', 'c']]

最新更新