1

I have a main list that looks like this:

a = [ [[1,2,3],[4,5,6]], [[7,8,9],[10,11,12]], [[13,14,15],[16,17,18]] ]

and I need to rearrange it to make it look like this:

b = [[1,2,3,7,8,9,13,14,15], [4,5,6,10,11,12,16,17,18]]

ie: take all the elements in the first sublists in each sublist of the main list and put them in a single sublist in the 0 position of a new list and then do the same for the second sublists and put all elements in a single sublist in position 1 of this new list.

I've tried zip combined with the solution given in Making a flat list out of list of lists in Python but I just can't get it to work.

Community
  • 1
  • 1
Gabriel
  • 40,504
  • 73
  • 230
  • 404

4 Answers4

2

Use zip with * and itertools.chain.from_iterable.

>>> from itertools import chain, izip
>>> [list(chain.from_iterable(x)) for x in zip(*a)] #or `izip`
[[1, 2, 3, 7, 8, 9, 13, 14, 15], [4, 5, 6, 10, 11, 12, 16, 17, 18]]

Here zip(*a) returns:

[([1, 2, 3], [7, 8, 9], [13, 14, 15]), ([4, 5, 6], [10, 11, 12], [16, 17, 18])]

Now you can flatten its items using chain.from_iterable(x).

Timing comparisons:

In [1]: from itertools import izip, chain
In [2]: a = [[[1,2,3],[4,5,6]], [[7,8,9],[10,11,12]], [[13,14,15],[16,17,18]]]
In [3]: %timeit [list(chain.from_iterable(x)) for x in zip(*a)]
100000 loops, best of 3: 3.71 us per loop
In [4]: %timeit [[i for v in r for i in v] for r in zip(*a)]
100000 loops, best of 3: 2.73 us per loop

In [5]: b = a *100
In [6]: %timeit [list(chain.from_iterable(x)) for x in zip(*b)]
10000 loops, best of 3: 97.6 us per loop
In [7]: %timeit [list(chain.from_iterable(x)) for x in izip(*b)]
10000 loops, best of 3: 97.6 us per loop
In [8]: %timeit [[i for v in r for i in v] for r in zip(*b)]
10000 loops, best of 3: 144 us per loop
In [9]: %timeit [[i for v in r for i in v] for r in izip(*b)]
10000 loops, best of 3: 143 us per loop

In [10]: c = a*10000
In [11]: %timeit [list(chain.from_iterable(x)) for x in zip(*c)]
100 loops, best of 3: 12.9 ms per loop
In [12]: %timeit [list(chain.from_iterable(x)) for x in izip(*c)]
100 loops, best of 3: 12.3 ms per loop
In [13]: %timeit [[i for v in r for i in v] for r in zip(*c)]
100 loops, best of 3: 17 ms per loop
In [14]: %timeit [[i for v in r for i in v] for r in izip(*c)]
100 loops, best of 3: 17.1 ms per loop
Community
  • 1
  • 1
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
1
>>> a = [[[1,2,3],[4,5,6]], [[7,8,9],[10,11,12]], [[13,14,15],[16,17,18]]]
>>>
>>> [[i for v in r for i in v] for r in zip(*a)]
[[1, 2, 3, 7, 8, 9, 13, 14, 15], [4, 5, 6, 10, 11, 12, 16, 17, 18]]

See: zip()

arshajii
  • 127,459
  • 24
  • 238
  • 287
1
a = [ [[1,2,3],[4,5,6]], [[7,8,9],[10,11,12]], [[13,14,15],[16,17,18]] ]
b = [[item for sitems in items for item in sitems] for items in zip(*a)]
print b

Output

[[1, 2, 3, 7, 8, 9, 13, 14, 15], [4, 5, 6, 10, 11, 12, 16, 17, 18]]
thefourtheye
  • 233,700
  • 52
  • 457
  • 497
0

Lists can be flattened by using sum() with the empty list as a first element, so you can use this:

[sum((item[0] for item in a), []), sum((item[1] for item in a), [])]

or this, for an arbitrary number of inner elements:

[sum((item[i] for item in a), []) for i in range(len(a[0]))]
yoniLavi
  • 2,624
  • 1
  • 24
  • 30