Dance Party2 Dance Party2 - 1 year ago 48
Python Question

Python Modify List of Lists

Given the following list of lists:

iters=[['EY11', 'EY12', 'EY13', 'EY14'],
['EY21', 'EY22', 'EY23', 'EY24'],
['PY11', 'PY12', 'PY13', 'PY14'],
['PY21', 'PY22', 'PY23', 'PY24']]

I'd like to modify this list to transpose the values (for lack of a better description) like this:

iters=[['EY11', 'EY21', 'PY11', 'PY21'],
['EY12', 'EY22', 'PY12', 'PY22'],
['EY13', 'EY23', 'PY13', 'PY23'],
['EY14', 'EY24', 'PY14', 'PY24']]

I can do this with one sub-list at a time like this:

[i[0] for i in iters]

but now I just need to know how to iterate through each sub-list and automatically make the new list of lists (also, I can't predict how many sub-lists there will be in my actual data, so I'd like to avoid hard-coding the current number of sub-lists in i[0].

Thanks in advance!

Answer Source

Most concise solution is to use the zip function with star unpacking:

newiters = list(zip(*iters))  # Wrapping in list not needed on Python 2

This will get almost what you want, but not quite, because it will be a list of tuples; if that's okay, you're done, if not, you just tweak it to convert to lists:

newiters = list(map(list, zip(*iters)))  # Wrapping in list not needed on Python 2

Reason this works is that star unpacking makes it as if you passed each element of iters as a sequential positional argument to zip, e.g.:

zip(['EY11', 'EY12', 'EY13', 'EY14'],
    ['EY21', 'EY22', 'EY23', 'EY24'],
    ['PY11', 'PY12', 'PY13', 'PY14'],
    ['PY21', 'PY22', 'PY23', 'PY24'])

And zip's whole schtick is making new tuples of values from matching offsets in a set of iterables, so the first tuple is the first element of each argument (('EY11', 'EY21', 'PY11', 'PY21')), the second is the second element of each argument (('EY12', 'EY22', 'PY12', 'PY22')), etc.

Note: This assumes all sub-lists are the same length. You'll lose data if they aren't, because zip stops when the shortest iterable is exhausted. You can use itertools.zip_longest to pad out shorter iterables to the length of the longest iterable if you like.