i have a list like this:
list1=[['milk', 'bread', 'eggs'], ['eggs', ['milk'], 'bread']]
I want to flatten (expected outcome):
list1=[['milk', 'bread', 'eggs'], ['eggs', 'milk', 'bread']]
I am using this code:
flat_list = []
for sublist in list1:
for item in sublist:
flat_list.append(item)
But i get back:
list1=['milk', 'bread', 'eggs', 'eggs', ['milk'], 'bread']
Any ideas?
CodePudding user response:
You can check if you're hitting a list or not and if it's a list, extend it, if not append it.
flat_list = []
for sublist in list1:
flat_list.append([])
for x in sublist:
if isinstance(x, list):
flat_list[-1].extend(x)
else:
flat_list[-1].append(x)
Output:
[['milk', 'bread', 'eggs'], ['eggs', 'milk', 'bread']]
But this wouldn't work if you have something like:
[['milk', ['bread', ['eggs']]]]
Or you can use the following function (that does not use recursion, so it will be faster):
def flatten_list(list1):
out = []
inside = list1
while inside:
x = inside.pop(0)
if isinstance(x, list):
inside = x inside
else:
out.append(x)
return out
out = [flatten_list(sublist) for sublist in list1]
flatten_list([['milk', ['bread', ['eggs']]]]) #['milk', 'bread', 'eggs']
CodePudding user response:
Here is the code that can solve your problem
list1 = [['milk', 'bread', 'eggs'], ['eggs', ['milk'], 'bread']]
flat_list = []
for i in list1:
temp_list =[]
for j in i:
if type(j) is list:
temp_list.append(j[0])
else:
temp_list.append(j)
flat_list.append(temp_list)
Now the flat_list
output is
[['milk', 'bread', 'eggs'], ['eggs', 'milk', 'bread']]
CodePudding user response:
You can use a recursive generator to flatten the list with an arbitrary nesting level (only limited by recursion depth):
list1=[['milk', 'bread', 'eggs'], ['eggs', ['milk'], 'bread']]
def flatten(iterable):
from collections.abc import Iterable
for item in iterable:
if isinstance(item, Iterable) and not isinstance(item, str):
yield from flatten(item)
else:
yield item
list(flatten(list1))
output: ['milk', 'bread', 'eggs', 'eggs', 'milk', 'bread']
To only flatten after the first level:
out = [list(flatten(l)) for l in list1]
output: [['milk', 'bread', 'eggs'], ['eggs', 'milk', 'bread']]
CodePudding user response:
Yet another one (this time using a recursive generator function):
list1 = [
['milk', 'bread', 'eggs'],
['eggs', ['milk'], 'bread'],
[[['eggs']], 'milk', [['bread']]]
]
def flatten(lst):
for item in lst:
if isinstance(item, list):
yield from flatten(item)
else:
yield item
list2 = [list(flatten(sublist)) for sublist in list1]
print(list2)
This will yield
[['milk', 'bread', 'eggs'], ['eggs', 'milk', 'bread'], ['eggs', 'milk', 'bread']]
CodePudding user response:
A recursive function is probably the easiest way to handle this:
def flatten(L):
return [f for v in L for f in flatten(v)] if isinstance(L,list) else [L]
list1=[['milk', 'bread', 'eggs'], ['eggs', ['milk'], 'bread']]
print(flatten(list1))
['milk', 'bread', 'eggs', 'eggs', 'milk', 'bread']
You could also use an iterative approach (doing it in-place for this example):
def flatten(L):
for i,_ in enumerate(L):
while isinstance(L[i],list):
L[i:i 1] = L[i]
list1=[['milk', 'bread', 'eggs'], ['eggs', ['milk'], 'bread']]
flatten(list1)
print(list1)
['milk', 'bread', 'eggs', 'eggs', 'milk', 'bread']
The use of enumerate() in the for loop is to continually get additional indexes as the list grows