Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Designate a variable as a list without overwriting it in a function

I created a function that will flatten a nested list into an ordinary list.

outputarray = []

def flattenarray(x):
    for elmt in x:
        if isinstance(elmt, float) or isinstance(elmt, int):
            outputarray.append(elmt)
        elif isinstance(elmt, list):
            flattenarray(elmt)
    return outputarray

The above works perfectly, but I am trying to have the "outputarray" variable inside the function, but when I do, the recursion step will overwrite the outputarray list back into an empty list.

How can I make this work to designate a list inside the function and at the same time be able to append to it without overwriting it during recursion?

like image 253
MetalicSt33l Avatar asked Oct 18 '25 23:10

MetalicSt33l


2 Answers

You will want to create the output array from within the function. One way to proceed is to pass the output container along in the recursive step:

def flattenarray(x, outputarray=None):
    if outputarray is None:
        outputarray = []
    for elmt in x:
        if isinstance(elmt, float) or isinstance(elmt, int):
            outputarray.append(elmt)
        elif isinstance(elmt, list):
            flattenarray(elmt, outputarray=outputarray)
    return outputarray

A more Pythonic approach is for the flattener to yield the items one-by-one. Note that isinstance can accept a tuple of types, so you only need to call it once.

def flatten(x):
    for elmt in x:
        if isinstance(elmt, (int, float, str, bytes)):
            yield elmt
        else:
            yield from flatten(elmt)

A more correctly duck-typing implementation:

def flatten(x):
    try:
        it = iter(x)
    except TypeError:
        yield x
        return
    if isinstance(x, (str, bytes)):
        yield x
        return
    for elem in it:
        yield from flatten(elem)
like image 177
wim Avatar answered Oct 20 '25 13:10

wim


This works perfectly with one line function and the basic idea is the same with wim:

def flatten(lst, outputarray=[]):
    return sum( ([x] if not isinstance(x, (list,tuple))  else flatten(x)
                     for x in lst), outputarray)


lst=[1,2,3,[2,4,5,[6]],(7,8,9)]

print(flatten(lst))

Result:

[1, 2, 3, 2, 4, 5, 6, 7, 8, 9]
like image 26
Marcus.Aurelianus Avatar answered Oct 20 '25 12:10

Marcus.Aurelianus