8

I have a list of tuples:

l=[(1,2,3),(4,5,6)]

The list can be of arbitrary length, as can the tuples. I'd like to convert this into a list or tuple of the elements, in the order they appear:

f=[1,2,3,4,5,6] # or (1,2,3,4,5,6)

If I know the at development time how many tuples I'll get back, I could just add them:

m = l[0] + l[1]  # (1,2,3,4,5,6)

But since I don't know until runtime how many tuples I'll have, I can't do that. I feel like there's a way to use map to do this, but I can't figure it out. I can iterate over the tuples and add them to an accumulator, but that would create lots of intermediate tuples that would never be used. I could also iterate over the tuples, then the elements of the tuples, and append them to a list. This seems very inefficient. Maybe there's an even easier way that I'm totally glossing over. Any thoughts?

technomalogical
  • 2,982
  • 2
  • 26
  • 43

7 Answers7

21

Chain them (only creates a generator instead of reserving extra memory):

>>> from itertools import chain
>>> l = [(1,2,3),(4,5,6)]
>>> list(chain.from_iterable(l))
[1, 2, 3, 4, 5, 6]
AndiDog
  • 68,631
  • 21
  • 159
  • 205
10
l = [(1, 2), (3, 4), (5, 6)]
print sum(l, ()) # (1, 2, 3, 4, 5, 6)
Cat Plus Plus
  • 125,936
  • 27
  • 200
  • 224
  • I always feel awful when I abuse `sum` this way. But that didn't stop it from popping into my head too. – Zach Kelling Feb 22 '12 at 19:06
  • What does `()` as the `start` value represent, or, how does this work?! An empty tuple? – Zach Young Feb 22 '12 at 19:12
  • For longer lists this will be very much slower than chain.from_iterable; it's O(n^2). [That said, I often do it myself when I know the list size is small and bounded.] – DSM Feb 22 '12 at 19:13
  • @DSM: Yeah, chain is better. But still, another solution is always nice. – Cat Plus Plus Feb 22 '12 at 19:26
  • +1 for succinctness, but I accepted the chain answer as the most efficient way to do this. – technomalogical Feb 22 '12 at 20:17
  • @ZacharyYoung: I had to look that up myself. If the sequence were empty, `sum` would return `0` rather than `()`. The `start=()` adds an empty tuple to the last tuple (resulting in no change) or, if the sequence is empty, is simply returned. – technomalogical Feb 22 '12 at 22:40
  • If start were 0, you'd get a type error, because you can't add int to a tuple. – Cat Plus Plus Feb 23 '12 at 12:14
2
reduce(tuple.__add__, [(1,2,3),(4,5,6)])
bluepnume
  • 16,460
  • 8
  • 38
  • 48
2
tuple(i for x in l for i in x) # (1, 2, 3, 4, 5, 6)
Fred
  • 1,011
  • 1
  • 10
  • 36
2

Use the pythonic generator style for all of the following:

b=[(1,2,3),(4,5,6)]

list = [ x for x in i for i in b ] #produces a list
gen = ( x for x in i for i in b ) #produces a generator
tup = tuple( x for x in i for i in b ) #produces a tuple

print list
>> [1, 2, 3, 4, 5, 6]
Matt Alcock
  • 12,399
  • 14
  • 45
  • 61
  • 1
    I just found this in the data structures tutorial: http://docs.python.org/tutorial/datastructures.html#list-comprehensions. +1 for a good example. – technomalogical Feb 23 '12 at 20:56
0
>>> from itertools import chain
>>> l = [(1,2,3),(4,5,6)]
>>> list(chain(*l))
[1, 2, 3, 4, 5, 6]
ChessMaster
  • 529
  • 1
  • 4
  • 12
0

You can combine the values in a list using the .extend() function like this:

l = [(1,2,3), (4,5,6)]
m = []
for t in l:
    m.extend(t)

or a shorter version using reduce:

l = [(1,2,3), (4,5,6)]
m = reduce(lambda x,y: x+list(y), l, [])
Wayne Werner
  • 49,299
  • 29
  • 200
  • 290
wobmene
  • 1,108
  • 9
  • 14
  • 1
    Lists have `.extend(iterable)`. No need to create a new list from `t`. – AndiDog Feb 23 '12 at 15:14
  • @MattAlcock all unbound list objects will be cleaned by garbage collector, correct? sorry, if I didn't understand your question right. – wobmene Feb 24 '12 at 09:43
  • @AndiDog thank you, didn't know about list.extend(iterable), variant with .extend should be better from any perspective – wobmene Feb 24 '12 at 09:54