Flatten an irregular (arbitrarily nested) list of lists
Using generator functions can make your example easier to read and improve performance.
Python 2
Using the Iterable
ABC added in 2.6:
from collections import Iterable
def flatten(xs):
for x in xs:
if isinstance(x, Iterable) and not isinstance(x, basestring):
for item in flatten(x):
yield item
else:
yield x
Python 3
In Python 3, basestring
is no more, but the tuple (str, bytes)
gives the same effect. Also, the yield from
operator returns an item from a generator one at a time.
from collections.abc import Iterable
def flatten(xs):
for x in xs:
if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
yield from flatten(x)
else:
yield x
Flatten nested list into 1-deep list
Replace the rapply
part by your own recursion so NULL
s are not getting any special treatment:
renquote <- function(l) if (is.list(l)) lapply(l, renquote) else enquote(l)
lapply(unlist(renquote(ml)), eval)
How to convert a nested list into a one-dimensional list in Python?
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']
Flatten nested lists in a list
Loop through the list, unlist recursively, then return as a list:
lapply(LIST2, function(i) list(unlist(i, recursive = TRUE)))
How do I make a flat list out of a list of lists?
Given a list of lists l
,
flat_list = [item for sublist in l for item in sublist]
which means:
flat_list = []
for sublist in l:
for item in sublist:
flat_list.append(item)
is faster than the shortcuts posted so far. (l
is the list to flatten.)
Here is the corresponding function:
def flatten(l):
return [item for sublist in l for item in sublist]
As evidence, you can use the timeit
module in the standard library:
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in l for item in sublist]'
10000 loops, best of 3: 143 usec per loop
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
1000 loops, best of 3: 969 usec per loop
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'reduce(lambda x,y: x+y,l)'
1000 loops, best of 3: 1.1 msec per loop
Explanation: the shortcuts based on +
(including the implied use in sum
) are, of necessity, O(L**2)
when there are L sublists -- as the intermediate result list keeps getting longer, at each step a new intermediate result list object gets allocated, and all the items in the previous intermediate result must be copied over (as well as a few new ones added at the end). So, for simplicity and without actual loss of generality, say you have L sublists of I items each: the first I items are copied back and forth L-1 times, the second I items L-2 times, and so on; total number of copies is I times the sum of x for x from 1 to L excluded, i.e., I * (L**2)/2
.
The list comprehension just generates one list, once, and copies each item over (from its original place of residence to the result list) also exactly once.
How to convert a nested list of strings to a one list?
If you're using the more_itertools
module try the collapse
function:
print(list(more_itertools.collapse(fruits)))
Output:
['apple', 'orange', 'pineapple', 'grapes']
How to flatten a hetrogenous list of list into a single list in python?
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)
Related Topics
How to Pass Aes Parameters of Ggplot to Function
R Dataframe: Aggregating Strings Within Column, Across Rows, by Group
Unique.Data.Table Select Last Row in Place of the First
R Plotly How to Get 3D Surface with Lat, Long and Z
R Dplyr Join on Range of Dates
Shiny Promises Future Is Not Working on Eventreactive
How to Dynamically Change Plotly Axis Based on Crosstalk Conditions
Extract Columns from Data Table by Numeric Indices Stored in a Vector
Running Out of Heap Space in Sparklyr, But Have Plenty of Memory
Error in Chol.Default(Cxx):The Leading Minor of Order Is Not Positive Definite
Plot Linear Regressions Lines Without Interaction in Ggplot2
How to Add a Title to Legend Scale Using Levelplot in R
Subset() a Factor by Its Number of Observation
Quantmod Omitting Tickers in Getsymbols
How to Neatly Align the Regression Equation and R2 and P Value