12

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?

4
  • 4
    my_list = list(map(lambda x :x[0], my_list)) Commented Dec 13, 2017 at 6:08
  • 2
    I sometimes miss Ruby when I write in Python : [[['item1','item2']], [['item3', 'item4']]].flatten(1). To be fair, it happens in both direction. Commented Dec 13, 2017 at 12:24
  • What did you research turn up, and why didn't the solutions in it work for your case? Commented Dec 13, 2017 at 22:54
  • What do you expect to a happen in the case where there are multiple items in the outer-most list? Commented Dec 14, 2017 at 5:33

9 Answers 9

24

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.

Sign up to request clarification or add additional context in comments.

7 Comments

I like the look of this too, but you shouldn't for more than very few elements: mathieularose.com/how-not-to-flatten-a-list-of-lists-in-python
Absolutely, since OP's list have few elements we can use this solution. And also I tried to post alteranative solution
No point doing timeits for minuscule input, it is almost never indicative of bigO performance.
The second method removes data if item has more than 1 element and raises an error if item is empty.
The sum approach is terrible, as it takes quadratic time for no good reason.
|
14

do the following:

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

3 Comments

Could do with one for loop: [i[0] for i in my_list]
@srig: The double list comprehension is cleaner IMHO. It also doesn't remove data if i has more than 1 element, and doesn't raise an error if i is empty.
@EricDuminil, I also thought the same, but then I went by the OP's input list :)
13

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.

Comments

6

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

Comments

6
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']]
>>> 

Comments

1

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.

Comments

0

python3

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

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

1 Comment

While this code snippet may solve the question, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion.
0

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]

1 Comment

no semicolons sure but why remove the column though?
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.