-2

I'm trying to remove all empty lists from a nested list recursively.

def listcleaner(lst):
   if isinstance(lst[0], int):
      return listcleaner(lst[1:])


   if isinstance(lst[0], list):
     if len(lst[0]) == []:
        lst[0].remove([])
        return listcleaner(lst)
     return listcleaner(lst[0])
   return lst

and what I'd like the function to do is

>>> a = listcleaner([1, [], [2, []], 5])
>>> print(a)
[1, [2], 5]
Vincent Savard
  • 34,979
  • 10
  • 68
  • 73
Dahab
  • 3
  • 4

4 Answers4

1

Every time you return, you are quitting the function. Here is the updated code:

def listcleaner(lst):
    if not lst:   # If list is empty
        return [] # Go no further
    if isinstance(lst[0], list):
        if lst[0]: # If the list has something in it, we want to run listcleaner() on it.
            return [listcleaner(lst[0])] + listcleaner(lst[1:])
        else: # Otherwise, just skip that list
            return listcleaner(lst[1:])
    else:
        return [lst[0]] + listcleaner(lst[1:]) # If it is not a list, return it unchanged plus listcleaner() on the rest.

a = listcleaner([1, [], [2, []], 5]) 
print(a)

Output:

[1, [2], 5]
zondo
  • 19,901
  • 8
  • 44
  • 83
  • this is not recursive – Dahab Feb 24 '16 at 20:18
  • It depends on how far I have to go in order for it to count as recursive. If you read through the whole code, you will see that I *do* call `listcleaner()` again to get sub-lists cleaned up. – zondo Feb 24 '16 at 20:19
  • It cannot use for or while loops. only if statements. – Dahab Feb 24 '16 at 20:20
  • @YousufMadi: Is it okay if `listcleaner()` returns `[1, 2, 5]`? I've written something that will do that, but I am still working on keeping the `2` as a list. – zondo Feb 24 '16 at 20:25
  • @YousufMadi: I just updated my answer. It has no `for` or `while` loops; just `if` statements. – zondo Feb 24 '16 at 20:57
  • @zondo thank you! would it be possible for you to edit and put logical comments. I promise this isnt a homework question Im just not completely understanding whats happening here. – Dahab Feb 25 '16 at 01:20
  • @YousufMadi: I just added the comments. If anything is unclear, let me know. – zondo Feb 25 '16 at 01:25
0

Something like this?

def listcleaner(lst):
    result = []
    for l in lst:
        if type(l) == list and len(l) > 0:
            result.append(listcleaner(l))
        elif type(l) != list:
            result.append(l)
    return result
Mad Wombat
  • 14,490
  • 14
  • 73
  • 109
  • Comparing `type(some_object)` to a type is not recommended. Instances of sub-classes would still return False. You should use `isinstance()` instead. See my answer. – zondo Feb 24 '16 at 20:16
  • Yeah but this isnt recursive, Im trying to do this recursively – Dahab Feb 24 '16 at 20:16
  • Do you see the `result.append(listcleaner(l))` line? – Mad Wombat Feb 24 '16 at 20:17
  • Yeah sorry the requirements say that I cannot use for loops or while loops though – Dahab Feb 24 '16 at 20:18
  • It looks like we are really in the same boat. – zondo Feb 24 '16 at 20:20
  • You might want to add those requirements (no loops) to your question. At any level of the list structure you will need to iterate through the elements at that level. For a true recursive pathway see here: http://stackoverflow.com/questions/21563271/recursively-going-through-a-list-python – roadrunner66 Feb 24 '16 at 20:50
0
def listcleaner(lst):
   n=len(lst)
   i=0
   while i < n :
        if isinstance(lst[i],list):
            if len(lst[i])==0:
                del lst[i]
                n=len(lst)
            else: 
                listcleaner(lst[i])
                i=i+1
        else:
            i=i+1
   return lst


a= listcleaner([1, [], [2, []], 5])
b= listcleaner([1,[],[2,[],[[],[],3]],5])
print(a)
print(b)

output:

[1, [2], 5]
[1, [2, [3]], 5]
roadrunner66
  • 7,772
  • 4
  • 32
  • 38
0

Hopefully this meets your criterion of being recursive:

def listcleaner(lst, result=None):
    if result is None:
        result = []
    if not isinstance(lst, list):
        return lst
    if not lst:
        return result
    head = listcleaner(lst[0])
    if head != []:
        result.append(head)
    return listcleaner(lst[1:], result)

Test:

>>> listcleaner([])
[]
>>> listcleaner([1, [], [2, []], 5])
[1, [2], 5]
>>> listcleaner([1, [], [2, [], [[], [], 3]], 5])
[1, [2, [3]], 5]

Caveat: I don't know what you want to do with nested cases like [[[]]]. On one interpretation of "remove all empty lists", since only the innermost list is empty, the function should just remove that and return [[]]. Another interpretation is that we should keep going until no empty list is left, and return []. My solution does the latter. (To be honest, haven't found a way to do the former ...)

gil
  • 2,086
  • 12
  • 13