0

I am trying to write a function called flatten_list that takes as input a list which may be nested, and returns a non-nested list with all the elements of the input list.

My code:

def flatten_list(alist):
    """
    >>> flatten_list([1,2,3])
    [1, 2, 3]
    >>> flatten_list([1, [2,3], [4, 5], 6])
    [1, 2, 3, 4, 5, 6]
    """
    flat_list = []
    for element in alist:
        flat_list += element
    return flat_list

This code works for lists with strings, but not integer values. How can I change the code so that it works for both?

thanks

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
codingwarrior
  • 39
  • 2
  • 5
  • 11

3 Answers3

2

Generally, this would be done recursively, for example:

def flatten(input_, output=None):
    if output is None:
        output = []
    if isinstance(input_, basestring):
        output.append(input_)
    else:
        for item in input_:
            try:
                flatten(item, output)
            except TypeError:
                output.append(item)
    return output

This will work with any combination of iterable containers (e.g. set, list, tuple, dict (keys only)) and contents (e.g. int, float, str), using the common EAFP Python style. Note the specific exception for strings, which you probably don't want to be unpacked!

A few examples of usage:

>>> flatten([1, [2, [3, [4, 5], 6], 7], 8])
[1, 2, 3, 4, 5, 6, 7, 8]
>>> flatten([1, "foo", ["bar", 2], 3])
[1, 'foo', 'bar', 2, 3]
>>> flatten([1, (2, 3), {4: 5}])
[1, 2, 3, 4]
>>> flatten("hello")
['hello']

And what happens with non-iterables as direct arguments:

>>> flatten(1)

Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    flatten(1)
  File "<pyshell#1>", line 4, in flatten
    for item in input_:
TypeError: 'int' object is not iterable
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
0

You can do it as:

a = [1, [2,3], [4, 5], 6]

def flatten(l,result = []):
    if isinstance(l, list):
        for i in l:
            flatten(i)
    else:
        result.append(l)
    return result

>>> print flatten(a)
[1, 2, 3, 4, 5, 6]

This will works for even deeper nesting levels:

>>> print flatten([1, [2, [3, 4]]])
[1, 2, 3, 4]

Demo

sshashank124
  • 31,495
  • 9
  • 67
  • 76
  • Firstly, `type(l) == int` should really be `isinstance(l, int)`, which handles inheritance better. Secondly, this *only* works if the final output is `int`. – jonrsharpe May 01 '14 at 12:27
  • @jonrsharpe, Thank you. I have updated my answer. It works better now. – sshashank124 May 01 '14 at 12:29
0

using collections.Iterable

from collections import Iterable
def flatten(items):
    for elem in items:
        if isinstance(elem,Iterable) and not isinstance(elem,str):
            for sub_elem in flatten(elem):
                yield sub_elem
        else:
            yield elem




 In [15]:   print list(flatten((1, (2,3), [4, 5],{10,11,12}, 6)))
 [1, 2, 3, 4, 5, 10, 11, 12, 6]


 In [16]: print list(flatten((1, (2,3), (4,5,6), 6)))
 [1, 2, 3, 4, 5, 6, 6]

 In [17]: print list(flatten([1, "foo", ["bar", 2], 3]))
 [1, 'foo', 'bar', 2, 3]
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321