John Bucel
John Bucel

Reputation: 181

Triple nested lists Python

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

Answers (9)

akash karothiya
akash karothiya

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

SigmaPiEpsilon
SigmaPiEpsilon

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

RoadRunner
RoadRunner

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

David Foerster
David Foerster

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

Ross Batten
Ross Batten

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

iruvar
iruvar

Reputation: 23364

python3

[[x], [y]] = my_list
print([x , y])

[['item1', 'item2'], ['item3', 'item4']]

Upvotes: 0

neehari
neehari

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

Vasif
Vasif

Reputation: 1413

my_list = list(map(lambda x :x[0], my_list))

Upvotes: 6

rawwar
rawwar

Reputation: 4992

do the following:

my_list = [j for i in my_list for j in i ]

Upvotes: 14

Related Questions