Flatten an irregular 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 an irregular 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
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)
Flatten an irregular list of lists in Python recursively
Your code is relying on a global; if the checker calls your function twice, it'll receive a longer list than expected:
>>> t = []
>>> def flatten(aList):
... for i in aList:
... if type(i) !=list:
... t.append(i)
... else:
... flatten(i)
... return t
...
>>> flatten([1, 1])
[1, 1]
>>> flatten([1, 1])
[1, 1, 1, 1]
>>> t # your global, still holding all those values:
[1, 1, 1, 1]
Don't use globals. Use a local list, and and extend it with the result of recursive calls:
def flatten(aList):
t = []
for i in aList:
if not isinstance(i, list):
t.append(i)
else:
t.extend(flatten(i))
return t
Note that I switched to using isinstance()
to test for the type. This version doesn't suffer from shared state leaking into the next call:
>>> def flatten(aList):
... t = []
... for i in aList:
... if not isinstance(i, list):
... t.append(i)
... else:
... t.extend(flatten(i))
... return t
...
>>> flatten([1, 1])
[1, 1]
>>> flatten([1, 1])
[1, 1]
>>> flatten([[[1]], [[[5]]]])
[1, 5]
>>> flatten([1, 1, [42, 81]])
[1, 1, 42, 81]
Convert an irregular list with multiple levels of nested lists to a list of lists
Generator function flatten is passed a list and looks at each sublist. If the length of the sublist is 0 or if the first element of the sublist is not another list, it just yields the sublist as the next list to be added to the result. Otherwise it recursively processes the sublist. Function nested_to_listoflist just assembles all of the "yielded" lists into one final list.
def flatten(l):
for el in l:
if not el or not isinstance(el[0], list):
yield el
else:
yield from flatten(el)
def nested_to_listoflist(l):
return [el for el in flatten(l)]
# or return list(flatten(l))
nested_list = [[[1, 2, 3], [[5, 6, 7], [8, 9, 10, 11, 23]]], [4], [[12, 13, 14], [[15, 16], [[17, 18], [19, 20]]]], [21, 22, 25, 26]]
unnested_list = nested_to_listoflist(nested_list)
print(unnested_list)
Prints:
[[1, 2, 3], [5, 6, 7], [8, 9, 10, 11, 23], [4], [12, 13, 14], [15, 16], [17, 18], [19, 20], [21, 22, 25, 26]]
Python Demo
Flatten a list of lists independent on content types and length and depth of sublists
import pydash
l = ["af", 2, [4.123, "ic", [-8, ["xdr"], -6]], [], [-2]]
pydash.flatten_depth(l,-1)
# output: ['af', 2, 4.123, 'ic', -8, 'xdr', -6, -2]
Flattening a list of strings and lists to work on each item
A more concise approach is:
for entry in initial_list:
for term in ([entry] if isinstance(entry, str) else entry):
do_something(term)
Flatten (an irregular) list of lists in Python respecting Pandas Dataframes
That flatten
function will recurse down if the element is an instance of collections.Iterable
and it's not a string (which is iterable, but we usually want to treat it as a scalar, something we're not going to look inside).
Even though DataFrames
are instances of collections.Iterable
, it sounds like you want them to be terminal too. In that case:
if (isinstance(el, collections.Iterable) and
not isinstance(el, (basestring, pandas.DataFrame))):
After which:
>>> list(flatten([[1,2], "2", df]))
[1, 2, '2', <class 'pandas.core.frame.DataFrame'>
Int64Index: 100 entries, 0 to 99
Data columns (total 4 columns):
A 100 non-null values
B 100 non-null values
C 100 non-null values
D 100 non-null values
Related Topics
Call to Operating System to Open Url
How to Clone a List So That It Doesn't Change Unexpectedly After Assignment
Why Is the Order in Dictionaries and Sets Arbitrary
Limiting Floats to Two Decimal Points
How to Break Out of Multiple Loops
What Are Type Hints in Python 3.5
Why Does Python Use 'Else' After For and While Loops
Get a List of Numbers as Input from the User
Pandas: How to Merge Two Dataframes on a Column by Keeping the Information of the First One
Run Interactive Bash With Popen and a Dedicated Tty Python
Relative Imports For the Billionth Time
Difference Between Re.Search and Re.Match
Error: Unable to Find Vcvarsall.Bat
Local Variables in Nested Functions