Search code examples
pythonpython-3.xrecursionreturnnonetype

Is "pre-checking" the preferred way to avoid adding None-types or empty strings when doing double recursion on lists?


I'm doing some recursion exercises on lists in python3 and was running into a problem where I would have my returned list filled with some unwwanted None-types.

This particular exercise is for creating a function that removes all vowel strings from a list. All the elements in the input list are strings of length one, but the list can contain more lists as well.

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:])

Expected output:

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

Initially, to "remove" the vowels upon detection I would simply not return anything. This resulted in None-types being added to the list.

Output without work-around (lines 10,11, 14-16 removed) :

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

To work around this problem I changed the code to return an empty string when vowels where found, and added a "pre-check" before calling on the function again to continue, basically just checking if the function call would find a vowel (and return "") and in that case skip ahead to the next part of the list argument.

I feel like I'm missing something obvious and there should be a better solution without using a work-around like this.

Thanks

Edit: This particular exercise is meant to be solved with double recursion, not with a combination of iteration and single recursion


Solution

  • This particular exercise is meant to be solved with double recursion, not with a combination of iteration and single recursion

    My approach to recursion is to keep it simple and let the recursion do the work for you:

    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)]
    

    USAGE

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