3

I have a list of arrays, where each array is a list of lists. I want to turn this into a single array with all the columns. I've tried using for loops to get this done, but it feels like it should be doable in list comprehension. Is there a nice one-liner that will do this?

    Example Input: [[[1,2],[3,4],[5,6]],[[7,8],[9,10],[11,12]]]
    
    Desired Output: [[1,2,7,8],[3,4,9,10],[5,6,11,12]]

Note: Example only has two arrays in the main list, but my actual data has much more, so I'm looking for something that works for N subarrays.

Edit: Example trying to solve this

Works for two but doesn't generalize:

[input[0][i]+input[1][i] for i in range(len(input[0]))]

These don't work, but show the idea:

[[element for table in input for element in row] for row in table]
[[*imput[j][i] for j in range(len(input))] for i in range(len(input[0]))]

Edit: Selected answer that uses only list comprehension and zip, but all answers (as of now) work, so use whichever fits your style/use case best.

Kalev Maricq
  • 617
  • 1
  • 7
  • 24

4 Answers4

5

You can generalize this from the standard list flattening pattern and zip:

>>> L = [[[1,2],[3,4],[5,6]],[[7,8],[9,10],[11,12]]]
>>> list([y for z in x for y in z] for x in zip(*L))
[[1, 2, 7, 8], [3, 4, 9, 10], [5, 6, 11, 12]]
>>> L = [[[1,2],[3,4],[5,6]],[[7,8],[9,10],[11,12]],[[13,14],[15,16],[17,18]]]
>>> list([y for z in x for y in z] for x in zip(*L))
[[1, 2, 7, 8, 13, 14], [3, 4, 9, 10, 15, 16], [5, 6, 11, 12, 17, 18]]
ggorlen
  • 44,755
  • 7
  • 76
  • 106
3

Here is one way of doing it:

initial = [[[1,2],[3,4],[5,6]],[[7,8],[9,10],[11,12]]]
output = [a+b for a, b in zip(*initial)]

print(output)

If you have more lists, this also works:

import itertools

initial = [[[1,2],[3,4],[5,6]],[[7,8],[9,10],[11,12]],[[13,14],[15,16],[17,18]]]
output = [list(itertools.chain.from_iterable(values)) for values in zip(*initial)]

print(output)
TheOneMusic
  • 1,776
  • 3
  • 15
  • 39
  • 1
    I like the idea of using zip, I didn't think of that. This appears to only work for two arrays in the list. Is there a way to generalize it? – Kalev Maricq Jul 19 '20 at 15:34
3

If you don't mind it is a tuple in the list.You could also try:

from itertools import chain
a = [[[1, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [11, 12]], [[13, 14], [15, 16], [17, 18]]]
output = list(map(list, map(chain.from_iterable, zip(*a))))

# [[1, 2, 7, 8, 13, 14], [3, 4, 9, 10, 15, 16], [5, 6, 11, 12, 17, 18]]
jizhihaoSAMA
  • 12,336
  • 9
  • 27
  • 49
2

This would do it, I named your input first:

[*map(lambda x: list(i for s in x for i in s), zip(*first))]
[[1, 2, 7, 8], [3, 4, 9, 10], [5, 6, 11, 12]]
Nicolas Gervais
  • 33,817
  • 13
  • 115
  • 143