Reputation: 181
I have a block of code that gives me a list that has some triple nested lists within it:
my_list = [[['item1','item2']], [['item3', 'item4']]]
And I would like to make it:
my_list = [['item1','item2'], ['item3', 'item4']]
Any suggestions?
Upvotes: 12
Views: 8373
Reputation: 5950
Use a list comprehension to select the single sub-sublist from each sublist:
>>> my_list = [item[0] for item in my_list]
[['item1', 'item2'], ['item3', 'item4']]
It's also possible to flatten out that level of nesting with sum
, but it's a performance disaster waiting to happen, since it has quadratic run-time:
In [5]: my_list = [[[i, i+1]] for i in range(0, 10000, 2)]
In [6]: %timeit sum(my_list, [])
78.6 ms ± 2.15 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [7]: %timeit [x[0] for x in my_list]
187 µs ± 3.05 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [8]: 78600/187
Out[8]: 420.32085561497325
That's a 420x slowdown for a 5000-length my_list
, which isn't a very long list at all. It's even worse for longer lists.
Upvotes: 24
Reputation: 698
A quick fix, provided you have similar structure of the nested lists the recursive function below (or something similar for other cases) can handle any level of nesting. Did not measure performance but it will be less compared to other solutions. Test well before use. In python 2.7
def f(x):
if hasattr(x[0], '__iter__'):
return f(x[0])
else:
return x
>>> my_list = [[['item1','item2']], [['item3', 'item4']]]
>>> [f(elem) for elem in my_list]
[['item1', 'item2'], ['item3', 'item4']]
>>> my_list = [[[['item1','item2']]], [['item3', 'item4']],[[[['item5', 'item6']]]]]
>>> [f(elem) for elem in my_list]
[['item1', 'item2'], ['item3', 'item4'], ['item5', 'item6']]
The hasattr() check will skip strings in python 2. Other tests like iter() may consider strings as iterable
Upvotes: 0
Reputation: 26315
A simple, but efficient way is to flatten your triple nested list with itertools.chain.from_iterable
:
>>> import itertools
>>> my_list = [[['item1','item2']],[['item3','item4']]]
>>> my_list = list(itertools.chain.from_iterable(my_list))
>>> my_list
[['item1', 'item2'], ['item3', 'item4']]
Which has O(n)
complexity for a list of size n
.
Upvotes: 13
Reputation: 1540
With map
and operator.itemgetter
:
map(operator.itemgetter(0), my_list)
In Python 3 that returns a generator. If you need a list
wrap the generator inside a list(...)
invocation.
Upvotes: 1
Reputation: 114
It's as simple as this if you want a quick fix -
for i in range(len(my_list)):
my_list[i]=my_list[i][0]
Upvotes: 0
Reputation: 23364
python3
[[x], [y]] = my_list
print([x , y])
[['item1', 'item2'], ['item3', 'item4']]
Upvotes: 0
Reputation: 2612
my_list = [[['item1','item2']],[['item3', 'item4']]]
One-liner with list comprehension
my_list = [sub[0] for sub in my_list]
You could also change my_list
in place:
my_list = [[['item1','item2']],[['item3', 'item4']]]
for i, sub in enumerate(my_list):
my_list[i] = sub[0]
>>> my_list
[['item1', 'item2'], ['item3', 'item4']]
>>>
Upvotes: 6