0

Given a nested list, such as

my_list = ['A', 'B', ['C', ['D', 'E'], 'F'], 'G']

Is there a way I can read the list level of each element, and return it such that:

new_list = [('A', 0), ('B', 0), [('C', 1), [('D', 2), ('E', 2)], ('F', 1)], ('G', 0)]

Any help or suggestions are greatly appreciated.

  • [Get nodes by level](/questions/52161783/get-all-nodes-on-a-given-level-in-a-binary-tree-with-python) contains most of your logic. See [How much research?](https://meta.stackoverflow.com/questions/261592/how-much-research-effort-is-expected-of-stack-overflow-users). Tree traversals in many forms are available with a direct browser search. We expect you to include this research in your post. – Prune May 20 '21 at 21:49
  • “Show me how to solve this coding problem” is not a Stack Overflow issue. We expect you to make an honest attempt, and *then* ask a *specific* question about your algorithm or technique. Stack Overflow is not intended to replace existing documentation and tutorials. – Prune May 20 '21 at 21:49

3 Answers3

2

You can use recursion:

my_list = ['A', 'B', ['C', ['D', 'E'], 'F'], 'G']
def to_level(d, l = 0):
  return [(a, l) if not isinstance(a, list) else to_level(a, l+1) for a in d]

print(to_level(my_list))

Output:

[('A', 0), ('B', 0), [('C', 1), [('D', 2), ('E', 2)], ('F', 1)], ('G', 0)]
Ajax1234
  • 69,937
  • 8
  • 61
  • 102
1

This is nasty and doesn't work if there are two identical letters in the list, but here it is, the idea might be useful for someone:

import re

def foo(my_list):
    s = str(my_list)
    letters = re.findall("'.'", s)
    for letter, tup in zip(letters, [f'({res}, {min(s.count("[", 0, s.index(res))-1, s.count("]", s.index(res))-1)})' for res in letters]):
        s = s.replace(letter, tup)
    return eval(s)

It stringifies the list, searches for the letters, then checks the number of brackets to its left and right so this way it can determine its level. Then the letters are replaced with the surrounding brackets accordingly and converted back to a list using eval.

zozo128
  • 59
  • 1
  • 3
1

You can also use a generator:

from collections.abc import Sequence
from typing import Any, Tuple


def get_level(value: Any, level: int = 0) -> Tuple[Any, int]:
    for item in value:
        if isinstance(item, Sequence):
            yield from get_level(item, level + 1)
            continue
        yield item, level


demo_list = ['A', 'B', ['C', ['D', 'E'], 'F'], 'G']
print(list(get_level(demo_list)))

demo_tuple = ('A', 'B')
print(list(get_level(demo_tuple)))

demo_single = 'A'
print(list(get_level(demo_single)))

Output:

[('A', 0), ('B', 0), ('C', 1), ('D', 2), ('E', 2), ('F', 1), ('G', 0)]
[('A', 0), ('B', 0)]
[('A', 0)]
DevLounge
  • 8,313
  • 3
  • 31
  • 44