8

I have list of lists of tuples:

a = [[(1, 2), (3, 4), (5, 6)], [(7, 8), (9, 10)]]

How can I make one list of tuples:

b = [(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]

Naive way is:

b = []
for c in a:
    for t in c:
        b.append(t)

List comprehension or any other ideas are welcome.

torayeff
  • 9,296
  • 19
  • 69
  • 103
  • 2
    `[i for b in a for i in b]`? – Ajax1234 May 05 '18 at 18:53
  • @Ajax1234 this is open question, i am interested in different approaches :) – torayeff May 05 '18 at 18:54
  • 1
    The best way IMO is using reduce from the functools module. `b = functools.reduce(list.__add__, a)` – Jack Homan May 05 '18 at 19:04
  • @Nick no it doesn't, it takes only the first element – torayeff May 05 '18 at 19:06
  • @JackHoman how is that "the best way"? It is a quadratic time algorithm when you can do it in linear time easily. – juanpa.arrivillaga May 05 '18 at 19:11
  • @juanpa.arrivillaga I said in my opinion. "Best" is probably the wrong way to describe it. It seems to be the most clear way to do it. What is the linear way to do it? – Jack Homan May 05 '18 at 19:15
  • `[x for sub in a for x in sub]` or an equivalent for-loop. – juanpa.arrivillaga May 05 '18 at 19:19
  • @juanpa.arrivillaga am I missing something? Theres two for loops in that list comprehension.... that's also quadratic running time. I just timed it and reduce is faster. Not trying to be argumentative. If I'm not understanding something, then I'd like to learn – Jack Homan May 05 '18 at 19:22
  • @JackHoman just because there are two for-loops doesn't make it quadratic time. Where `n` is the number of elements in all the sublists, then that is O(N) time, it only touches each element once. Using `+` you get a *new list each time* each intermediate step, touching all the elments you already touched again and again... – juanpa.arrivillaga May 05 '18 at 19:31
  • @juanpa.arrivillaga oh okay, that makes sense. Thanks – Jack Homan May 05 '18 at 19:37
  • @JackHoman just for good measure, here's some empirical evidence: https://gist.github.com/juanarrivillaga/0ed8e599cbc8a8605abbe919df84c5fa – juanpa.arrivillaga May 05 '18 at 19:45
  • @juanpa.arrivillaga that's really interesting. When I timed it, reduce seemed to be faster every time. I guess I should probably do it at a larger scale before making assumptions – Jack Homan May 05 '18 at 19:47

3 Answers3

11

Using itertools

demo:

import itertools
a = [[(1, 2), (3, 4), (5, 6)], [(7, 8), (9, 10)]]
print(list(itertools.chain(*a)))

Output:

[(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]
Rakesh
  • 81,458
  • 17
  • 76
  • 113
8

This operation is called 'flatten' in some of other languages. In python, followings method might be shortest.

a = [[(1, 2), (3, 4), (5, 6)], [(7, 8), (9, 10)]]
sum(a, [])
// [(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]

It also work in the case the parent list have many child lists.

b = [[1],[2],[3],[4],[5]]
sum(b, [])
// [1, 2, 3, 4, 5]
set0gut1
  • 1,652
  • 1
  • 8
  • 21
5

You don't want to append, you want to extend. You can use the really simple loop

a = [[(1, 2), (3, 4), (5, 6)], [(7, 8), (9, 10)]]
single_level_list = []
for lst in a:
    single_level_list.extend(lst)

print(single_level_list)

>>> [(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]
Nick Chapman
  • 4,402
  • 1
  • 27
  • 41