1

I have a list of tables, where each table is a list of lists. I'd like to extract the columns from each table to get a lists of columns. An example should clarify:

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

I know I can probably use several for loops, but it feels like there should be a nice one liner to do this.

I intend to assign the results to variables:

a,b,_=output

With a single table, I can extract the columns with:

>>>input=[[1,2,3],[4,5,6]]
>>>list(zip(*input))
[(1, 4), (2, 5), (3, 6)]

or for assignment:

>>>a,b,_=zip(*input)
>>>a
(1, 4)
>>>b
(2, 5)

But for a list of tables, I haven't been able to do it. Here are some of the things I've tried unsuccessfully:

>>>list(zip(*zip(*input)))
[([1, 2, 3], [4, 5, 6]), ([7, 8, 9], [10, 11, 12]), ([13, 14, 15], [16, 17, 18])]
>>>[list(zip(*inp)) for inp in input]
[[(1, 4), (2, 5), (3, 6)], [(7, 10), (8, 11), (9, 12)], [(13, 16), (14, 17), (15, 18)]]
>>>[[x,y,z] for x,y,z in [zip(*inp) for inp in input]]
#same as above
>>> [[x,y] for inp in input for x,y in zip(*inp)]
[[1, 4], [2, 5], [3, 6], [7, 10], [8, 11], [9, 12], [13, 16], [14, 17], [15, 18]]

And nested/unpacked assignment didn't work for me either:

>>>[[a,b,_]]=[zip(*inp) for inp in input]
ValueError: too many values to unpack (expected 1)
>>>[*a,*b,*_]=[[x,y] for x,y in [zip(*inp) for inp in input]]
SyntaxError: two starred expressions in assignment

Is there a one-liner to do what I'm trying to do?

Edit: Note that while the example is specifically 3 tables with 2 rows and 3 columns each, my actual use case has unknown numbers of tables and rows.

I ended up using this line in my code:

list(zip(*[zip(*inp) for inp in input]))

1 Answer 1

1

You got close with that last attempt. You need one more, well-chosen nesting level. EDIT: I added the final zip step to get the desired ordering. I also used that "star" notation to help show how to extend the concept.

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

f1 = [[[a, b] for a, b in zip(list1, list2)] for list1, list2 in given]
print(f1)
f2 = list(zip(*f1))
print(f2)

Output (edited for readability)

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

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

The second one has tuples instead of lists at the middle level; is that okay? If not, can you fix it? (left as an exercise for the student ... )

Sign up to request clarification or add additional context in comments.

6 Comments

Is there a way to make this work for columns of any length?
It already does work for the third dimension. If you want it to work for the first two, simply trade in the pair of variables, replacing with "star" expansion, such as *var. Is that enough to make it clear?
The *var makes sense. Looking at this more though, it appears it does something slightly different than what I'm looking for. Applying this to my original input I get: [[[1, 4], [2, 5], [3, 6]], [[7, 10], [8, 11], [9, 12]], [[13, 16], [14, 17], [15, 18]]]
(1) As best I can see, the output you posted is identical to the desired output. (2) If you need to ask another question, please post it separately. Comments are not a good place to solve coding difficulties.
I'm not sure what you're looking at, but my desired output is the one with [7,10] as the second pair.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.