-1

I want to expand list in list that included in some not-iterable objects to flat.
I tried to do this using list comprehension, but I get an error in not-iterable objects.
How to expand this list to flat?

# [[1, 2], 3] -> [1, 2, 3]
list = [[1, 2], 3]
flat = [item for sublist in list for item in sublist] # TypeError: 'int' object is not iterable
print(flat)

In my environment, numpy is installed in addition to the standard functions.
I tried numpy.concatenate(list).flat, but I get an error.

# [[1, 2], 3] -> [1, 2, 3]
list = [[1, 2], 3]
flat = numpy.concatenate(list).flat # ValueError: all the input arrays must have same number of dimensions, but the array at index 0 has 1 dimension(s) and the array at index 1 has 0 dimension(s)
print(flat)
Sanjay SS
  • 568
  • 4
  • 14
ken
  • 65
  • 8
  • 1
    Sorry, it is not **iterable** object. I made a spelling mistake. – ken Oct 23 '21 at 23:58
  • Do you include all iterable types in this ? For example, if the list contains "ABC", do you expect it to come out as "A", "B", "C" ? If not, then you'll need a solution that is more specific on iterable types – Alain T. Oct 24 '21 at 00:02

4 Answers4

3

If the iterables are only lists and only one level deep, you can do it in the list comprehension.

L    = [[1, 2], 3]
flat = [v for item in L for v in (item if isinstance(item,list) else [item])]

If there are multiple levels and a variety of iterable types, you will probably need a recursive function:

def flatten(L):
    if not isinstance(L,(list,tuple,set)): # you probably don't want str here
        yield L
        return
    for F in L:
        yield from flatten(F)

L    = [[1, 2], 3, ({5,6,7},[8,9],10)]
flat = list(flatten(L))

print(flat)
[1, 2, 3, 5, 6, 7, 8, 9, 10]
Alain T.
  • 40,517
  • 4
  • 31
  • 51
3

You could try this to see if that what's you're looking for:

It can flatten any levels (deeply nested) by recursively calling itself. Just be aware this did not do performance test yet, so there may be room to improve it.

import collections

def flatten(L):
    if isinstance(L, collections.Iterable):
        return [a for i in L for a in flatten(i)] # recursively calling
    else:
        return [L]

Running it:

lst = [[1, 2], 3, [[4, 5], 6] ]
print(flatten(lst))     # [1, 2, 3, 4, 5, 6]
lst2 =  [[1, 2], 3, [[4, 5, [6]]], 7, 8]
print(flatten(lst2))    #  [1, 2, 3, 4, 5, 6, 7, 8]  # deeply nested
Daniel Hao
  • 4,922
  • 3
  • 10
  • 23
1

There may be more elegant solutions, but the trivial one would be to just iterate with a couple of for loops, checking value type:

flat = []
for item in list:
    try:
        for subitem in item:
            flat.append(subitem)
    except TypeError: # Not iterable, append as is
        flat.append(item)

Note this assumes the nesting is only one level deep.

Lev M.
  • 6,088
  • 1
  • 10
  • 23
0

First of all, I highly recommend avoid identifiers such as list, dict, set etc. as these are data-types from Python and even though the syntax is allowed, you will "hide" them from the usage in your application.

Also, as a suggestion, avoid using list comprehension for more complex operations, as they can become difficult to read.

I recommend the following approach:

my_list = [[1, 2], 3]
flat = []
for item in my_list:
    if isinstance(item, list):
        for val in item:
            flat.append(val)
    else: flat.append(item)
print(flat)

Using list comprehension, the solution would look like:

my_list = [[1, 2], 3]

flat = [v for item in my_list for v in (item if isinstance(item,list) else [item])]
print(flat)
pyhalex
  • 19
  • 2