1

I am know how to easily flatten a list of lists. For example:

my_list = [['abc'],[1,2,3]]
list(itertools.chain.from_iterable(my_list))

But if

my_list = ['abs',[1,2,3]]
list(itertools.chain.from_iterable(my_list))

I get ['a','b','c',1,2,3], while I want ['abc', 1,2,3]

I can solve this problem by running a for loop for the second element in the original list, but that seems like a messy way to do it, and becomes really messy if you don't know which element in a list is a list, and which is a string.

Is there a simple way to flatten a list that has both lists and string in it?

AK9309
  • 761
  • 3
  • 13
  • 33
  • Use [this](http://stackoverflow.com/a/952952/2588818) answer but put a check for string types. I'd say how to do that but it's different whether you're using Python 2 or Python 3, and you haven't said. – Two-Bit Alchemist Dec 07 '15 at 21:43
  • Ok, then: `[item for sublist in my_list for item in sublist if not isinstance(sublist, basestring)]` – Two-Bit Alchemist Dec 07 '15 at 21:50

1 Answers1

1

You can use reduce with a lambda function

l = lambda x,y: (x if isinstance(x,list) else [x]) + (y if isinstance(y,list) else [y])
reduce(l, my_list)

Example

>>> my_list = [['abc'],[1,2,3]]
>>> reduce(l, my_list)
['abc', 1, 2, 3]

>>> my_list = ['abs',[1,2,3]]
>>> reduce(l, my_list)
['abs', 1, 2, 3]

That way, you literally reduce a list of separte things to one list of these things.

It works with as many lists inside lists you want. For instance:

>>> my_list = ['abs',[1,2,[3,4]]]
>>> tmp = reduce(l, my_list)
#tmp = ['abs', 1, 2, [3,4]] - Just run again
>>> reduce(l, tmp)
>>> ['abs', 1, 2, 3, 4]

It should be noticed that this is not an efficient method, as highlighted by Two-bit Alchemist

rafaelc
  • 57,686
  • 15
  • 58
  • 82