Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Most programmatically elegant (pythonic) way to take ith element of list of lists of lists, and create lists of these ith elements

Tags:

python

list

Say that you have a list of lists, of lists, for example

lll = [(['a', 'b'], [1, 2], [True, False]),
       (['c'], [3], [True]),
       (['d', 'e', 'f', 'g'], [4, 5, 6, 7], [True, False, True, False])]

For each item in lll, I would like a list of the ith element in each of the items list, and I want all these lists in one list.

This is very tricky to describe with words as you can imagine, but I would like the final result to be like this

result = [
['a', 1, True],
['b', 2, False].
['c', 3, True],
['d', 4, True],
['e', 5, False],
['f', 6, True],
['g', 7, False]
]

What I tried so far is

newList = []
for item in lll:
    num_things = len(item[0])
    for ii in range(num_things):
        newList.append([x[ii] for x in item])

newList

Is there a more pythonically elegant way to get this result?

like image 294
SantoshGupta7 Avatar asked Jan 24 '23 11:01

SantoshGupta7


2 Answers

Your original code isn't bad at all. These existing answers are great, but I think

result = []

for item in lll:
    result.extend(zip(*item))

is reasonably succinct and Pythonic, arguably more readable than a one-liner, no imports and worth consideration. extend is a common refactor for append + loop for flattening lists and zip is almost always the way to go for columnwise iteration and matrix rotation.

If you need lists instead of tuples:

result = []

for item in lll:
    result.extend([list(x) for x in zip(*item)])

or with map:

for item in lll:
    result.extend(map(list, zip(*item)))

A couple of minor style suggestions courtesy of PEP-8:

  • snake_case is preferred over camelCase.
  • Avoid l as a variable name. It's too easily confused for i and 1.

Also, num_things = len(item[0]) strikes me as a bit dangerous because it'll raise an IndexError if item is empty.

like image 152
ggorlen Avatar answered Feb 03 '23 07:02

ggorlen


Simple one-liner with no imports:

[[*ys] for xss in lll for ys in zip(*xss)]

The zip-star transposes, the second for concatenates, and the inner square brackets convert the tuples from the zip to lists.

like image 37
gilch Avatar answered Feb 03 '23 08:02

gilch