2

Having this list

l = [['a', 'b', 'c', 'd'],[[["d","d"]],['z', 'x', 'g', 'd'], ['z', 'C', 'G', 'd']]]

I would like to get a function extracting all nested lists and return

l = [['a', 'b', 'c', 'd'],["d","d"],['z', 'x', 'g', 'd'], ['z', 'C', 'G', 'd']]

like flatten but keeping the list formation of every nested list. This is the closest I have been and I feel like there is a way of accomplishing my goal without using an extra structure to filter duplicates. Also, order matters in string and list level.

def get_all_nested_list(l,returned_list):
    nested_list = l
    while isinstance(nested_list, list):
        for elem in nested_list:
            get_all_nested_list(elem,returned_list)
        if isinstance(nested_list[0], str):
            returned_list.append(nested_list)
        nested_list = nested_list[0]


if __name__ == '__main__':
    l = [['a', 'b', 'c', 'd'],[[["d","d"]],['z', 'x', 'g', 'd'], ['z', 'C', 'G', 'd']]]
    l2 = []
    get_all_nested_list(l,l2)
    print(l2)

Any other ways of doing it the above either by using itertools or suggesting an actually proper way of using yield instead of passing another list as argument are more than welcome.

Alex R.
  • 459
  • 5
  • 16
  • This looks like a good case for `more_itertools.collapse()` https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.collapse – AutomaticStatic Feb 22 '20 at 05:27
  • 1
    The answer to this question is here: [How to remove all unnecessary arrays in nd array](https://stackoverflow.com/questions/60128295/how-to-remove-all-unnecessary-arrays-in-nd-array/60131589#60131589) . I remember because I wrote a recursive function in a hurry for the answer but the end accepted solution was far better and I kicked myself for not thinking of it first. – Rahul P Feb 22 '20 at 05:32
  • @RahulP It fails since lists are of different nested levels. It returns [['a', 'b', 'c', 'd'], [[['d', 'd']], ['z', 'x', 'g', 'd'], ['z', 'C', 'G', 'd']]] – Alex R. Feb 22 '20 at 14:23
  • @AutomaticStatic I am not sure how someone can implement it with this function since the lists are of different nested levels which is the primary reason I posted this question. – Alex R. Feb 22 '20 at 14:55

2 Answers2

4

You could try a recursive function

my_nested_list = [['a', 'b', 'c', 'd'],[[["d","d"]],['z', 'x', 'g', 'd'], ['z', 'C', 'G', 'd']]]

def flatten(nested_list):
    for item in nested_list:
        if not isinstance(item[0],list):
            yield item
        else:
            yield from flatten(item)

flat_list = [item for item in flatten(my_nested_list)]
print(flat_list)
Thomas
  • 1,026
  • 7
  • 18
  • 1
    recursion in a generator. I like it. – Todd Feb 22 '20 at 05:33
  • In case `my_nested_list = [['a', 'b', 'c', 'd'],['e', [["d","d"]],['z', 'x', 'g', 'd'], ['z', 'C', 'G', 'd']]]`, this code gives `[['a', 'b', 'c', 'd'], ['e', [['d', 'd']], ['z', 'x', 'g', 'd'], ['z', 'C', 'G', 'd']]]`. Right? – Wesley Yang Feb 22 '20 at 06:38
  • **ONE QUESTION::** **In the above case, Is THIS CODE correct?** – Wesley Yang Feb 22 '20 at 06:49
  • @TopDeveloper I didn't explicitly state it but every element supposed to be a list. My bad, my question's specifications were not strict enough. That's because I change completely implementation in my program and didn't have to use lists but I still have the query which I posted. The code above is not particularly wrong for my not so specific request. – Alex R. Feb 22 '20 at 14:47
1

You can do it like this:

from itertools import chain 

my_nested_list = [['a', 'b', 'c', 'd'],['e', ['r'], [["d","d"]],['z', 'x', 'g', 'd'], ['z', 'C', 'G', 'd']]]

def flatten(nested_list):
    for item in nested_list:
        if not isinstance(item,list):
            yield item
        elif list(chain(*item)) == item:
            yield item
        else:
            yield from flatten(item)

flat_list = list(flatten(my_nested_list))
# [['a', 'b', 'c', 'd'], 'e', ['r'], ['d', 'd'], ['z', 'x', 'g', 'd'], ['z', 'C', 'G', 'd']]

Thanks

Wesley Yang
  • 366
  • 1
  • 6