23

Say I have a list of tuples like [(1,2), (1,3), (1,4), (1,5), (1,6)]. I'm trying to convert it to a simple list like [1,2,1,3,1,4,1,5,1,6].

How do I do this without having to iterate through each element and add the items one by one to another list?

Are there any fast and efficient ways to do this without actually iterating through the original list of tuples? Perhaps a built-in function or method?

8
  • I don't think there is a way to do it without implicitly iterating through the tuples. Commented Sep 10, 2012 at 16:11
  • @jonathanmarvens: I think by "without having to iterate through each element`, the OP meant using an explicit for loop. Commented Sep 10, 2012 at 16:23
  • Of course, "[e for l in lst for e in l]" (from David Robinson's answer) is the fastest way to do it, but I think it would be impossible to do this "without [implicitly] actually iterating through the original list of tuples". Even if you use some "built-in function/method", that's what it has to do under-the-hood. Commented Sep 10, 2012 at 16:24
  • @DavidRobinson OK. I just wanted to make sure he understands that. Commented Sep 10, 2012 at 16:25
  • I understand there is probably no way to do it without IMPLICITLY iterating through the tuples. @DavidRobinson is right. I was trying to avoid EXPLICITLY using a 'for' loop. Commented Sep 10, 2012 at 16:26

4 Answers 4

39
lst = [(1,2), (1,3), (1,4), (1,5), (1,6)] import itertools list(itertools.chain(*lst)) # [1, 2, 1, 3, 1, 4, 1, 5, 1, 6] 

Alternatively:

[e for l in lst for e in l] # [1, 2, 1, 3, 1, 4, 1, 5, 1, 6] 
Sign up to request clarification or add additional context in comments.

4 Comments

I sure will. I am also gonna try the list comprehension. I have a couple of benchmarks I'm running. It just might get my work done faster since I won't import any module. @ovgolovin also suggested something below that I'd try out to see if it's faster.
@davidadamojr According to this excellent answer, the list comprehension version is faster.
@DavidRobinson They have made a lot of optimizations since the time of that answer. A lot may have changed since. Especially major speed-related changes were in Python 3. To be sure, speed test should be performed in the current version of Python that one uses.
@DavidRobinson Here is the article by BDFL where he writes about it: python-history.blogspot.com/2010/06/…
12

Fundamentally, which one is faster? Using the "itertools" module, or using a list comprehension? I'm basically trying to improve my computation speed here. - @davidadamojr

I've been doing some tests and I find that the code below is actually faster.

list_ = [(1, 2), (1, 3), (1, 4), (1, 5), (1, 6)] list(sum(list_, ())) 

Someone correct me if I'm wrong.

Here are some tests below.

>>> list_ = [(1, 2), (1, 3), (1, 4), (1, 5), (1, 6)] >>> >>> operation_1 = lambda: [tuple_item for tuple_ in list_ for tuple_item in tuple_] >>> def operation_2 (): final_list = [] for tuple_ in list_: for tuple_item in tuple_: final_list.append(tuple_item) return final_list >>> operation_3 = lambda: reduce(list.__add__, map(list, list_)) >>> def operation_4 (): import itertools return list(itertools.chain(*list_)) >>> operation_5 = lambda: list(sum(list_, ())) >>> >>> operation_1() [1, 2, 1, 3, 1, 4, 1, 5, 1, 6] >>> operation_2() [1, 2, 1, 3, 1, 4, 1, 5, 1, 6] >>> operation_3() [1, 2, 1, 3, 1, 4, 1, 5, 1, 6] >>> operation_4() [1, 2, 1, 3, 1, 4, 1, 5, 1, 6] >>> operation_5() [1, 2, 1, 3, 1, 4, 1, 5, 1, 6] >>> >>> import timeit >>> >>> print('operation_1 completed in %s seconds.' % (timeit.timeit(operation_1))) operation_1 completed in 1.57890490223 seconds. >>> print('operation_2 completed in %s seconds.' % (timeit.timeit(operation_2))) operation_2 completed in 2.90350501659 seconds. >>> print('operation_3 completed in %s seconds.' % (timeit.timeit(operation_3))) operation_3 completed in 5.08437990236 seconds. >>> print('operation_4 completed in %s seconds.' % (timeit.timeit(operation_4))) operation_4 completed in 3.85125378138 seconds. >>> print('operation_5 completed in %s seconds.' % (timeit.timeit(operation_5))) operation_5 completed in 1.2623826489 seconds. 

3 Comments

And of course, none of these operations flatten recursively. They only flatten at a single level. To avoid rewriting something that someone else has done, click here to visit an article on recursive flattening. It's an old article (from 2006), but I don't think that should be an issue.
Hey @jonathanmarvens, I ran the tests also and indeed operation_5 seems the fastest. Great!
@davidadamojr I'm glad it works for you! If you don't mind, I would appreciate it if you would vote up my answer. Thanks.
9

Use chain.from_iterable, as it avoids unnecessary all-at-once unpacking (which leads to redundant memory consumption) by lazily advancing through list:

>>> import itertools >>> L = [(1,2), (1,3), (1,4), (1,5), (1,6)] >>> list(itertools.chain.from_iterable(L)) [1, 2, 1, 3, 1, 4, 1, 5, 1, 6] 

1 Comment

This is the simplest, most pythonic answer. It should be higher.
1

Here is the best way to do it in terms of performance and independence of special modules like itertools:

>>> l = [(1,2), (1,3), (1,4), (1,5), (1,6)] >>> reduce(list.__add__,map(list,l)) [1, 2, 1, 3, 1, 4, 1, 5, 1, 6] 

1 Comment

Is this faster and more efficient than using a list comprehension as shown in some of the answers above?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.