How to Flatten Lists Without Splitting Strings

How can I flatten lists without splitting strings?

Solution:

def flatten(foo):
for x in foo:
if hasattr(x, '__iter__') and not isinstance(x, str):
for y in flatten(x):
yield y
else:
yield x


Old version for Python 2.x:

def flatten(foo):
for x in foo:
if hasattr(x, '__iter__'):
for y in flatten(x):
yield y
else:
yield x

(In Python 2.x, strings conveniently didn't actually have an __iter__ attribute, unlike pretty much every other iterable object in Python. Note however that they do in Python 3, so the above code will only work in Python 2.x.)

Flatten a list of strings and lists of strings and lists in Python

The oft-repeated flatten function can be applied to this circumstance with a simple modification.

from collections import Iterable
def flatten(coll):
for i in coll:
if isinstance(i, Iterable) and not isinstance(i, basestring):
for subc in flatten(i):
yield subc
else:
yield i

basestring will make sure that both str and unicode objects are not split.

There are also versions which count on i not having the __iter__ attribute. I don't know about all that, because I think that str now has that attribute. But, it's worth mentioning.

(Please upvote the linked answer.)

Split and flatten a list of strings

try:

res = []    
for i in lst:
res.extend(i.split(","))

Another option is to use reduce:

res = list(reduce(lambda a, b: a + b.split(','), lst, []))

Flattening a nested list in Python

arr = [['31', '1'], '32', ['8', '16'], ['1', '3', '12'], ['4', '12'], '32', ['1', '3', '12'], ['4', '12'], '32', ['30', '1', '1']]

def extract(array):
for item in array:
if type(item) in [set, list, tuple]:
yield from extract(item)
continue
yield item

print(list(extract(arr))) # ['31', '1', '32', '8', '16', '1', '3', '12', '4', '12', '32', '1', '3', '12', '4', '12', '32', '30', '1', '1']

Flatten list of list of strings

If you have a list of strings of Python expressions that represent lists (how's that for a nested clause), you will have to use ast.literal_eval() to get back to reality, as it were.

>>> import ast
>>> list1 = ["['word']", "['second', 'first']", "['first']"]
>>> list2 = [ast.literal_eval(item) for item in list1]
[['word'], ['second', 'first'], ['first']]

Using ast.literal_eval(), as opposed to the dangerous eval() that you shouldn't use is safe, as it only evaluates literals that can have no side effects.

How to split strings inside a list by given delimiter and flatten the sub-strings lists

It would probably be easier to make a new list:

blocks = [
"item-1",
"item-2",
"item-3.0;item-3.1;item-3.2"
]

new_blocks = []

for block in blocks:
for c in block.split(";"):
new_blocks.append(c)

# new_blocks = ['item-1', 'item-2', 'item-3.0', 'item-3.1', 'item-3.2']

Flatten a list and a string

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



Related Topics



Leave a reply



Submit