4

I have a list of objects where objects can be lists or scalars. I want an flattened list with only scalars. Eg:

L = [35,53,[525,6743],64,63,[743,754,757]]
outputList = [35,53,525,6743,64,63,743,754,757]

P.S. The answers in this question does not work for heterogeneous lists. Flattening a shallow list in Python

Community
  • 1
  • 1
balki
  • 26,394
  • 30
  • 105
  • 151
  • this works if pop() returns a only one scalar at a time http://stackoverflow.com/a/10546929/1321404 you can modify this code with if len(returned_pop_element)>1 then call recursive function again for returned_pop_element(list). – Dmitry Zagorulkin May 17 '12 at 08:23
  • Also see: http://stackoverflow.com/questions/5828123/nested-list-and-count/5828872 – sateesh May 17 '12 at 08:26
  • see also https://stackoverflow.com/a/40857703/4531270 – pylang Aug 28 '18 at 23:02

11 Answers11

10

Here is a relatively simple recursive version which will flatten any depth of list

l = [35,53,[525,6743],64,63,[743,754,757]]

def flatten(xs):
    result = []
    if isinstance(xs, (list, tuple)):
        for x in xs:
            result.extend(flatten(x))
    else:
        result.append(xs)
    return result

print flatten(l)
Nick Craig-Wood
  • 52,955
  • 12
  • 126
  • 132
  • I think I can make it `isinstance(xs,collections.Iterable) and not isinstance(xs,str)` so that it includes `set` and other possible iterables as well. – balki May 18 '12 at 06:50
  • `and not isinstance(xs,basestring)` for python < 3, but yes good idea – Nick Craig-Wood May 18 '12 at 07:00
5

it could be done neatly in one line using numpy

import numpy as np
np.hstack(l)

you end up with an ndarray

array([  35,   53,  525, 6743,   64,   63,  743,  754,  757])
nye17
  • 12,857
  • 11
  • 58
  • 68
5
>>> data = [35,53,[525,6743],64,63,[743,754,757]]
>>> def flatten(L):
        for item in L:
            if isinstance(item,list):
                for subitem in item:
                    yield subitem
            else:
                yield item


>>> list(flatten(data))
[35, 53, 525, 6743, 64, 63, 743, 754, 757]

Here is a one-liner version for code-golf purposes (it doesn't look good :D )

>>> [y for x in data for y in (x if isinstance(x,list) else [x])]
[35, 53, 525, 6743, 64, 63, 743, 754, 757]
jamylak
  • 128,818
  • 30
  • 231
  • 230
3
l = [35,53,[525,6743],64,63,[743,754,757]]
outputList = []

for i in l:
    if isinstance(i, list):
        outputList.extend(i)
    else:
        outputList.append(i)
jamylak
  • 128,818
  • 30
  • 231
  • 230
Vikas
  • 8,790
  • 4
  • 38
  • 48
  • @jamylak, thanks for editing, but i like two spaces for indentation :-( – Vikas May 17 '12 at 09:22
  • @jamylak, thanks for the ref. I always thought that the recommendation is to use spaces. Did not know it was 4 spaces. – Vikas May 17 '12 at 09:29
  • Yeah but of course they are filled in by the editor when you press tab anyway. It is usually set to 4 or 3 by default. Also for some reason i cannot write @Vikas at the beginning of my comments, I don't know why it is not letting me... – jamylak May 17 '12 at 09:31
1

Here's a oneliner, based on the question you've mentioned:

list(itertools.chain(*((sl if isinstance(sl, list) else [sl]) for sl in l)))

UPDATE: And a fully iterator-based version:

from itertools import imap, chain
list(chain.from_iterable(imap(lambda x: x if isinstance(x, list) else [x], l)))
Community
  • 1
  • 1
ubik
  • 4,440
  • 2
  • 23
  • 29
1
outputList = []
for e in l:
    if type(e) == list:
        outputList += e
    else:
        outputList.append(e)

>>> outputList
[35, 53, 525, 6743, 64, 63, 743, 754, 757]
jamylak
  • 128,818
  • 30
  • 231
  • 230
Maria Zverina
  • 10,863
  • 3
  • 44
  • 61
0
def nchain(iterable):
    for elem in iterable:
        if type(elem) is list:
            for elem2 in elem:
                yield elem2
        else:
            yield elem
Christian Witts
  • 11,375
  • 1
  • 33
  • 46
0

Recursive function that will allow for infinite tree depth:

def flatten(l):
    if isinstance(l,(list,tuple)):
        if len(l):
            return flatten(l[0]) + flatten(l[1:])
        return []
    else:
        return [l]

>>>flatten([35,53,[525,[1,2],6743],64,63,[743,754,757]])
[35, 53, 525, 1, 2, 6743, 64, 63, 743, 754, 757]

I tried to avoid isinstance so as to allow for generic types, but old version would infinite loop on strings. Now it flattens strings correctly (Not by characters now, but as if it's pretending a string is a scalar).

Josiah
  • 3,266
  • 24
  • 24
0
>>> L = [35,53,[525,6743],64,63,[743,754,757]]
>>> K = []
>>> [K.extend([i]) if type(i) == int else K.extend(i) for i in L ]
[None, None, None, None, None, None]
>>> K
[35, 53, 525, 6743, 64, 63, 743, 754, 757]
fraxel
  • 34,470
  • 11
  • 98
  • 102
0

This solution is only for your specific situation (scalars within lists) and assumes the scalars are integer. It is a terrible solution but it is incredibly short.

outputlist = map(int,",".split(str(L).replace("[","").replace("]","")))
Tuomas Laakkonen
  • 1,280
  • 10
  • 15
0

The answer is quite simple. Take advantage of recursion.

def flatten(nst_lst, final_list):

    for val in nst_lst:
        if isinstance(val, list):
            flatten(val, final_list)
        else:
            final_list.append(val)
    return final_list

#Sample usage
fl_list = []
lst_to_flatten = [["this",["a",["thing"],"a"],"is"],["a","easy"]]

print(flatten(lst_to_flatten, fl_list))