Home > Software design >  Python: Efficient unrolling/flattening list of tuples and single floats
Python: Efficient unrolling/flattening list of tuples and single floats

Time:05-11

I have a list of tuples and single floats

v = [(1., 2., 3.), (4., 5.), 6., 7.]

Now I want to flatten it with the good old list comprehension

[item for sublist in v for item in sublist]

But an error occurs as single floats are not iterable. What is the most efficient way to unroll this mixed list? I tried to go through the list and use isininstance() but once again, the list is not iterable.

EDIT: time comparisons so far

  • numpy approach with hstack: 6.49 µs ± 100 ns per loop
  • hasattr approach: 398 ns ± 2.11 ns per loop
  • collections approach: 804 ns ± 1.27 ns per loop

CodePudding user response:

You can use hasattr to check if the object is iterable (has a __iter__ method):

out = [item for sublist in v
       for item in (sublist if hasattr(sublist, '__iter__') else [sublist])]

output: [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]

An alternative would be to use collections.abc:

from collections.abc import Iterable
    
out = [item for sublist in v
       for item in (sublist if isinstance(sublist, Iterable) else [sublist])]   

Note that in both cases, strings are considered iterable, you might want to check for this specific case depending on your data.

CodePudding user response:

With numpy you can use hstack():

v = [(1., 2., 3.), (4., 5.), 6., 7.]
v = np.hstack(v)

# Output
array([1., 2., 3., 4., 5., 6., 7.])

CodePudding user response:

The more-itertools package has a function specifically for this problem -

from more_itertools import collapse
v = [(1., 2., 3.), (4., 5.), 6., 7.]
print(list(collapse(v))
[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]

It works with strings too -

x = [('ab', 'cd'), 'e', ['f', 'gh']]
print(list(collapse(x))
['ab', 'cd', 'e', 'f', 'gh']
  • Related