Skip to content Skip to sidebar Skip to footer

How To Write A Recursive Function That Takes A List And Return The Same List Without Vowels?

I am supposed to write a recursive function that takes a list of strings or a list of lists of strings and return the list without vowels, if found. Here is my attempt to solve it:

Solution 1:

def no_vowel(seq):
    if not isinstance(seq, list):
        raise ValueError('Expected list, got {}'.format(type(seq)))
    if not seq:
        return []
    head, *tail = seqif isinstance(head, list):
        return [[no_vowel(head)]] + no_vowel(tail)
    else:
        ifheadin'aeiou':
            return no_vowel(tail)
        else:
            return [head] + novowel(tail)   

The cool unpacking of the list is a Python 3 feature, and is very similar to functional programmings pattern matching.

Solution 2:

return the same list without vowels

Eh, you're slicing the original list in the recursive calls, so you have a copy not the same list.

More so, your code actually works, but since you're passing a slice of the list, the vowel items in the slice (not the original list) are deleted and the original remains unchanged.

You can instead use a non-slicing variant that moves from start to end indices of the original list:

def no_vow(seq, index=0):
    keys = ['a','i','e','o','u']
    ifnot seq ornot isinstance(seq, list) orindex >= len(seq):
        returnelse:
        if seq[index] in keys:
            del seq[index]return no_vow(seq, index)
        else:
            return no_vow(seq, index+1)

Finally, if you're going to print your result, you shouldn't print the output of the function call (which will be None) but the list.


Trial:

li = ["b", "c", "e", "d", "a"]

no_vow(li) # list is modified in-place
print(li)
# ["b", "c", "d"]

Solution 3:

Your base case returns a None. So whenever you passes the empty list the None is sent up the stack of recursive calls.

Moreover you are not storing the characters which are not vowels, so your else case is wrong.

What you can have is something like this:

>>> def noVow(seq):
...     keys = ['a','i','e','o','u','u']
...     ifnot seq ornot isinstance(seq, list) :
...         return []
...     else:
...         if seq[0] in keys:
...             return noVow(seq[1:])
...         else:
...             return [seq[0]] + noVow(seq[1:])

Also seq[0:] is equivalent to seq.

Solution 4:

To work for a list of lists containing string and a flat list of strings, you need to iterate over the sequence and then check the type:

defnoVow(seq):
    vowels = {'a', 'i', 'e', 'o', 'u', 'u'}
    for ele in seq:
        ifisinstance(ele, list):
            # a list so recursively processyield [s for s in noVow(ele)]
        # else it has to be a string so just see if it is not a vowelelif ele notin vowels:
            yield ele

You use it like:

In [39]: li
Out[39]: [['b', 'c'], ['d', 'a']]

In [40]: li[:] = noVow(li)

In [41]: print(li)
[['b', 'c'], ['d']]

In [42]: li = ["a","b","c","e"]

In [43]: li[:] = noVow(li)

In [44]: print(li)
['b', 'c']
In [10]: li = [["b", "c"], ["d", ["a"]]]
In [11]: li[:] = noVow(li)   
In [12]: li
Out[12]: [['b', 'c'], ['d', []]] # works for nested lists

If you wanted a flat list of all non-vowels and you can use python3, you can use yield from:

defnoVow(seq):
    vowels = {'a', 'i', 'e', 'o', 'u', 'u'}
    for ele in seq:
        ifisinstance(seq, list):
            yieldfrom noVow(ele)
        elif ele notin vowels:
            yield ele

You use it the same way:

In [2]: li = [["b", "c"], ["d", "a"]]

In [3]: li[:] = noVow(li)

In [4]: li
Out[4]: ['b', 'c', 'd']

In [5]: li = ["a","b","c","e"]

In [6]: li[:] = noVow(li)

In [7]: li
Out[7]: ['b', 'c']

You can do the same with python2, you just need another loop

Solution 5:

I believe this solution correctly implements both of the criteria "a list of strings or a list of lists of strings" and "return the same list" without any external assistance:

defnoVowels(sequence, index=0):
    ifnot (sequence andtype(sequence) islistand index < len(sequence)):
        return 

    vowels = {'a','i','e','o','u'}

    iftype(sequence[index]) islist:
        noVowels(sequence[index])
    elif sequence[index] in vowels:
        del sequence[index]
        index -= 1

    noVowels(sequence, index + 1)

    return sequence

TEST

array = [['a', 'b', 'c', 'd', 'e'], 'f', 'g', 'h', 'i', ['l', 'm', ['n', 'o', 'p'], 'q'], 'r', 's', 't', 'u']

print(array)
print(id(array))
print(id(array[0]))

result = noVowels(array)

print(result)
print(id(result))
print(id(result[0]))

RESULT

> python3 test.py
[['a', 'b', 'c', 'd', 'e'], 'f', 'g', 'h', 'i', ['l', 'm', ['n', 'o', 'p'], 'q'], 'r', 's', 't', 'u']
4315447624
4315344520
[['b', 'c', 'd'], 'f', 'g', 'h', ['l', 'm', ['n', 'p'], 'q'], 'r', 's', 't']
4315447624
4315344520
>

Note that the same list, and inner lists, are left intact based on their id not changing. And it handles a list of lists of lists.

I don't believe it's functional program because it works by side-effect but that contradiction is inherent in the OP's problem description.

Post a Comment for "How To Write A Recursive Function That Takes A List And Return The Same List Without Vowels?"