Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flatten an irregular list of lists

Yes, I know this subject has been covered before (here, here, here, here), but as far as I know, all solutions, except for one, fail on a list like this:

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

Where the desired output is

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

Or perhaps even better, an iterator. The only solution I saw that works for an arbitrary nesting is found in this question:

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

Is this the best model? Did I overlook something? Any problems?

like image 622
telliott99 Avatar asked Jan 28 '10 22:01

telliott99


People also ask

How do you flatten a list of lists?

Flatten List of Lists Using itertools (chain()) This approach is ideal for transforming a 2-D list into a single flat list as it treats consecutive sequences as a single sequence by iterating through the iterable passed as the argument in a sequential manner.

How do you deep flatten a list in Python?

To flatten a nested list we can use the for loop or the While loop or recursion or the deepflatten() Method. Other techniques include importing numerous external Python libraries and using their built-in functions.

What does flatten a list mean?

Flattening lists means converting a multidimensional or nested list into a one-dimensional list. For example, the process of converting this [[1,2], [3,4]] list to [1,2,3,4] is called flattening.


2 Answers

Using generator functions can make your example a little easier to read and probably boost the performance.

Python 2

def flatten(l):     for el in l:         if isinstance(el, collections.Iterable) and not isinstance(el, basestring):             for sub in flatten(el):                 yield sub         else:             yield el 

I used the Iterable ABC added in 2.6.

Python 3

In Python 3, the basestring is no more, but you can use a tuple of str and bytes to get the same effect there.

The yield from operator returns an item from a generator one at a time. This syntax for delegating to a subgenerator was added in 3.3

from collections.abc import Iterable  def flatten(l):     for el in l:         if isinstance(el, Iterable) and not isinstance(el, (str, bytes)):             yield from flatten(el)         else:             yield el 
like image 69
Cristian Avatar answered Sep 29 '22 22:09

Cristian


My solution:

import collections   def flatten(x):     if isinstance(x, collections.Iterable):         return [a for i in x for a in flatten(i)]     else:         return [x] 

A little more concise, but pretty much the same.

like image 42
Josh Lee Avatar answered Sep 29 '22 23:09

Josh Lee