How to convert a nested list into a one-dimensional list in Python? [duplicate]
Asked Answered
A

15

33

I tried everything (in my knowledge) from splitting the array and joining them up together and even using itertools:

import itertools

def oneDArray(x):
    return list(itertools.chain(*x))

The result I want:

a) print oneDArray([1,[2,2,2],4]) == [1,2,2,2,4]

Strangely, it works for

b) print oneDArray([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) == [1, 2, 3, 4, 5, 6, 7, 8, 9]

Question 1) How do I get part a to work the way I want (any hints?)

Question 2) Why does the following code above work for part b and not part a??

Abjuration answered 5/7, 2013 at 9:40 Comment(1)
I couldn't find the answer I was looking for in SO because none of my search results returned anything about "flatten" but the answers given here helped clear things up alot!Abjuration
S
29

You need to recursively loop over the list and check if an item is iterable(strings are iterable too, but skip them) or not.

itertools.chain will not work for [1,[2,2,2],4] because it requires all of it's items to be iterable, but 1 and 4 (integers) are not iterable. That's why it worked for the second one because it's a list of lists.

>>> from collections import Iterable
def flatten(lis):
     for item in lis:
         if isinstance(item, Iterable) and not isinstance(item, str):
             for x in flatten(item):
                 yield x
         else:        
             yield item

>>> lis = [1,[2,2,2],4]
>>> list(flatten(lis))
[1, 2, 2, 2, 4]
>>> list(flatten([[1, 2, 3], [4, 5, 6], [7, 8, 9]]))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

Works for any level of nesting:

>>> a = [1,[2,2,[2]],4]
>>> list(flatten(a))
[1, 2, 2, 2, 4]

Unlike other solutions, this will work for strings as well:

>>> lis = [1,[2,2,2],"456"]
>>> list(flatten(lis))
[1, 2, 2, 2, '456']
Sissy answered 5/7, 2013 at 9:42 Comment(1)
If using python 3, replace basestring with str.Bagby
T
23

If you're using python < 3 then you can do the following:

from compiler.ast import flatten
list = [1,[2,2,2],4]
print flatten(list)

The manual equivalent in python 3.0 would be (taken from this answer):

def flatten(x):
    result = []
    for el in x:
        if hasattr(el, "__iter__") and not isinstance(el, str):
            result.extend(flatten(el))
        else:
            result.append(el)
    return result

 print(flatten(["junk",["nested stuff"],[],[[]]]))  

You could even do the same in a list comprehension:

list = [1,[2,2,2],4]
l = [item for sublist in list for item in sublist]

Which is the equivalent of:

l = [[1], [2], [3], [4], [5]]
result = []
for sublist in l:
    for item in sublist:
        result.append(item)

print(result)
Trite answered 5/7, 2013 at 10:38 Comment(1)
That import "compiler.ast" blew my mind! ... it's even easier than all the answers that included yield.. but one thing though I tried the list comprehension answe (which I ideally want the answer in that form since I did Haskell before) r you gave but it gave "TypeError: 'int' object is not iterable" =(Abjuration
B
11

To Make A Single list from a Nested List in python we can simply do this :

from functools import reduce

some_list = [[14], [215, 383, 87], [298], [374], [2,3,4,5,6,7]]
single_list = reduce(lambda x,y: x+y, some_list)
print(single_list)

Output: [14, 215, 383, 87, 298, 374, 2, 3, 4, 5, 6, 7]

Berkeley answered 1/2, 2019 at 12:22 Comment(0)
P
6
from nltk import flatten

example_list = [1, [2, 3], 3]
flattened_list = flatten(example_list)
print(flattened_list)

Output: [1, 2, 3, 3]

Pyxie answered 28/11, 2019 at 6:13 Comment(0)
M
2

itertools.chain() iterates through each item in the inputted list (refer to the docs I linked). Because you can't iterate through integers, the error is raised. That is why in the second example, you only have lists in the list and no integers alone, thus no integers are actually being iterated through.

To get it working, you can use recursion:

>>> from collections import Iterable
>>> def flat(lst):
...     for parent in lst:
...         if not isinstance(i, Iterable):
...             yield parent
...         else:
...             for child in flat(parent):
...                 yield child
...
>>> list(flat(([1,[2,2,2],4]))
[1, 2, 2, 2, 4]
Merla answered 5/7, 2013 at 9:43 Comment(0)
F
2

Use more_itertools

import more_itertools

nested_test1 = [[-1, -2], [1, 2, 3, [4, (5, [6, 7])]], (30, 40), [25, 35]]
nested_test2 = [1,[2,2,2],4]
lis = [1,[2,2,2],"456"]

print(list(more_itertools.collapse(nested_test1)))
print(list(more_itertools.collapse(nested_test2)))
print(list(more_itertools.collapse(lis)))

OUTPUT

[-1, -2, 1, 2, 3, 4, 5, 6, 7, 30, 40, 25, 35]
[1, 2, 2, 2, 4]
[1, 2, 2, 2, '456']
Frayne answered 5/2, 2020 at 7:9 Comment(0)
R
2

You don't have to use append. just use extend

def flatten(nasted_list):
    """
    input: nasted_list - this contain any number of nested lists.
    ------------------------
    output: list_of_lists - one list contain all the items.
    """

    list_of_lists = []
    for item in nasted_list:
        list_of_lists.extend(item)
    return list_of_lists

test1 = flatten([[1,2,3],[4,5,6]])
print(test1)

output: [1, 2, 3, 4, 5, 6]

Reversal answered 29/7, 2020 at 11:26 Comment(0)
W
0

It's actually quite easy without using itertools, you can simply iterate over a list and if the loop will encounter another list you will simply iterate over nested list. Here's the code:

def flatten(l):
    flatList = []
    for elem in l:
        # if an element of a list is a list
        # iterate over this list and add elements to flatList 
        if type(elem) == list:
            for e in elem:
                flatList.append(e)
        else:
            flatList.append(elem)
    return flatList


a = [1,[2,2,2],4]  # flatten(a) returns [1, 2, 2, 2, 4]
b =  [[1, 2, 3], [4, 5, 6], [7, 8, 9]] # flatten(b) returns [1, 2, 3, 4, 5, 6, 7, 8, 9]
Willingham answered 5/7, 2013 at 9:58 Comment(1)
Fails for [1,[2,2,[2]],4].Sissy
S
0

If it is going to be only one level of list of lists, then the simplest solution is:

lis = [1,[2,2,2],"456"]
output = []
for item in lis:
    if isinstance(item, (str, int, bool)):
        output.append(item)
    elif isinstance(item, dict):
        for i in item.items():
            output.extend(i)
    else:
        output.extend(list(item))

Why I used extend(list(item)) is that even if there is a set within your items, it will not cause any problem. This will handle items as string, integer, boolean, dictionary, list as well as a tuple.

Shurlock answered 5/7, 2013 at 10:34 Comment(0)
N
0
old_list = [1,2,3,['a','b'],4,5,6,['c','d',[11,22,33,'aa','bb','cc',[111,222,333,['aaa','bbb','ccc',[1111,2222,['aaaa','bbbb',[11111,22222]]]]]],'e']]

new_list = []

def my_fun(temp_list):
    for ele in temp_list:
        if type(ele) == list:
            my_fun(ele)
        else:
            new_list.append(ele)


my_fun(old_list)
print old_list
print new_list

output:
old_list = [1, 2, 3, ['a', 'b'], 4, 5, 6, ['c', 'd', [11, 22, 33, 'aa', 'bb', 'cc', [111, 222, 333, ['aaa', 'bbb', 'ccc', [1111, 2222, ['aaaa', 'bbbb', [11111, 22222]]]]]], 'e']]
new_list = [1, 2, 3, 'a', 'b', 4, 5, 6, 'c', 'd', 11, 22, 33, 'aa', 'bb', 'cc', 111, 222, 333, 'aaa', 'bbb', 'ccc', 1111, 2222, 'aaaa', 'bbbb', 11111, 22222, 'e']

Use recursion to convert multi nested list into single sliced list.

Nitrosamine answered 12/7, 2016 at 11:46 Comment(0)
D
0
def flatten_out_nested_list(input_list):
    if input_list is None:
        return None
    if not isinstance(input_list, (list, tuple)):
        return None
    flattened_list = []
    for entry in input_list:
        entry_list = None
        if not isinstance(entry, list):
            try:
                entry_list = ast.literal_eval(entry)
            except:
                pass
        if not entry_list:
            entry_list = entry
        if isinstance(entry_list, list):
            flattened_entry = flatten_out_nested_list(entry_list)
            if flattened_entry:
                flattened_list.extend(flattened_entry)
        else:
            flattened_list.append(entry)
    return flattened_list

nested_list = [[1,2,3,4,5],[6,7,8,9,10]]
flattened_list = flatten_out_nested_list(nested_list)

OUTPUT: [1,2,3,4,5,6,7,8,9,10]

Dashtikavir answered 26/12, 2019 at 21:31 Comment(0)
C
0

This flatten_nlevel function will flatten or converts the n-level nested list to one level. Try this out

def flatten_nlevel(list1, flat_list):
    for sublist in list1:
        if isinstance(sublist, type(list)):        
            flatten(sublist, flat_list)
        else:
            flat_list.append(sublist)

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

items = []
flatten(l,items)
print(items)

output:

[1, 1, 2, 3, 4, 6, 4, 5]
Crick answered 4/5, 2020 at 12:5 Comment(0)
R
0

Use the pipe package

from pipe import chain


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

list(lst|chain)

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

Ruelu answered 23/2, 2022 at 7:7 Comment(0)
E
0
list1 = [[1,2,3], 2, 4,[4,5,6],[7,8,9]] 
flat_list = []
for item in list1:
    if type(item) == list:
        flat_list = flat_list+item
    else:
        flat_list.append(item)

output: [1, 2, 3, 2, 4, 4, 5, 6, 7, 8, 9]

Eozoic answered 30/4, 2022 at 9:29 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Jotter

© 2022 - 2024 — McMap. All rights reserved.