Flattening multiple nested list

Supposing I have a multiple nested list of following structure:

['p', [['p', 'q'], [['~p', '~r'], [['r', '~s'], ['s', '~q']]]]]

where every second element of nested list is another nested list (except for innermost list), I want to output to extract all list with the strings such that my output appears as follows:

['p', ['p', 'q'], ['~p', '~r'], ['r', '~s'], ['s', '~q']]

I have implemented the following code:

def flatten_nested_list(nested_list):
    flat_list = []
    for item in nested_list:
        if isinstance(item, list) and isinstance(item[1], list):
            flat_list.append(item[0])
            flat_list.extend(flatten_nested_list(item[1]))
        else:
            flat_list.append(item)
    return flat_list

nested_list = ['p', [['~p', 'q'], [['~p', '~r'], [['r', '~s'], ['s', '~q']]]]]
flat_result = flatten_nested_list(nested_list)
print(flat_result)

However my function does not handle the innermost list properly and my output is as follows:

['p', ['~p', 'q'], ['~p', '~r'], ['r', '~s'], 's', '~q']

Can any change be suggested so that the innermost list be handled properly ?

>Solution :

IIUC, you can use recursion:

lst = ["p", [["p", "q"], [["~p", "~r"], [["r", "~s"], ["s", "~q"]]]]]


def flatten(lst):
    if isinstance(lst[-1], list):
        yield lst[0]
        yield from flatten(lst[-1])
    else:
        yield lst


print(list(flatten(lst)))

Prints:

['p', ['p', 'q'], ['~p', '~r'], ['r', '~s'], ['s', '~q']]

EDIT:

lst = ["p", [["~p", "q"], [["~q", "r"], "~r"]]]


def flatten(lst):
    match [lst[0], lst[1]]:
        case str(), list():
            yield lst[0]
            yield from flatten(lst[1])
        case list(), list():
            yield from flatten(lst[0])
            yield from flatten(lst[1])
        case list(), str():
            yield from flatten(lst[0])
            yield lst[1]
        case _:
            yield lst


print(list(flatten(lst)))

Prints:

['p', ['~p', 'q'], ['~q', 'r'], '~r']

Leave a Reply