Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flattening a multilevel list of lists to a single level

I need to flatten all the levels of a multi-level list:

import itertools

pool = [[[[[0,2],[1,3]],[[3,2],[1,0]]],"PdPd","PrisonerDilemma"], 
[[[[0,3],[1,2]],[[2,3],[1,0]]],"ShSh","StagHunt"],
[[[[1,2],[3,0]],[[3,2],[1,0]]],"ChCh","Chicken"],
[[[[2,1],[0,3]],[[3,1],[0,2]]],"BaBa","Battle"]]

def flat3 (pool):
    for game in pool:
        l = list(itertools.chain.from_iterable(game[0]))
        print(l)

The result:

flat3 (pool)
[[0, 2], [1, 3], [3, 2], [1, 0]]
[[0, 3], [1, 2], [2, 3], [1, 0]]
[[1, 2], [3, 0], [3, 2], [1, 0]]
[[2, 1], [0, 3], [3, 1], [0, 2]]

So, the objective is to isolate and return the first level in each item, containing only the numbers, such as:

[[[[[0,2],[1,3]],[[3,2],[1,0]]],"PdPd","PrisonerDilemma"]

Then I need everything to be flattened to the same level, like:

[0,2,1,3,3,2,1,0]

I know there is a lot of material on this topic and I have found and tried many ways of doing this, however none seems to work with more than one level, I want to know if there is an efficient way to do this, without repeating the same command many times. Could anyone help me?

like image 374
vferraz Avatar asked Oct 29 '25 14:10

vferraz


1 Answers

The first step, as usual, is to look at your data structure.

el = [
         [
             [[0,2],[1,3]],
             [[3,2],[1,0]]
         ],
         "PdPd",
         "PrisonerDilemma"
     ]

This is each individual element in your structure. We'll ignore for the time being that this outermost structure almost certainly shouldn't be a list (it looks more like a tuple to me) and just focus on what we've got.

el[0] = [ [[0, 2], [1, 3]],
          [[3, 2], [1, 0]] ]
el[1] = # a string
el[2] = # another string, we don't care about these

Now we've reduced it to a list of lists of LISTS of numbers. This one we can operate on.

def flatten(lst):
    for el in lst:
        if isinstance(el, list):  # N.B. this only works for lists, not general
                                  # collections e.g. sets, tuples, dicts, etc...
            # recurse
            yield from flatten(el)
        else:
            # generate
            yield el

your result then being to apply this function to the first element of each item in the outermost list.

result = [flatten(sublst[0]) for sublst in big_list]

Note that this creates a list of generator objects, which need to be consumed to actually produce values. If you actually need the lists themselves for some reason, cast to list explicitly:

result = [list(flatten(sublst[0])) for sublst in big_list]
like image 170
Adam Smith Avatar answered Oct 31 '25 05:10

Adam Smith



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!