Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pythonically unpacking nested list values from a dictionary [duplicate]

This question here goes nearly where I want. However, my dictionary has a list inside a list for each key, such as:

test = {1092268: [[81, 90], [78, 90]], 
        524292: [[80, 80], [65, 78]], 
        892456: [[88, 81], [81, 88]]}

The suggestion that Works when there is just one list inside each key is:

xs, ys = zip(*test.values())

How can I unpack (still xs and ys), but from multiple lists?

For the example, the results I expect are:

xs = [81, 78, 80, 65, 88, 81]
ys = [90, 90, 80, 78, 81, 88]
like image 747
B Furtado Avatar asked Mar 06 '23 04:03

B Furtado


2 Answers

Not much changes, just flatten your values in advance.

itertools.chain

from itertools import chain
xs, ys = zip(*chain.from_iterable(test.values()))

Of course, this returns tuples. If you want lists instead, I recommend adding a map call—

xs, ys = map(list, zip(*chain.from_iterable(test.values())))

print(xs)
[81, 78, 80, 65, 88, 81]

print(ys)
[90, 90, 80, 78, 81, 88]

Comprehension-based

This is the alternative, squash nested loops into a single line (i.e., a nested list comprehension)—

xs, ys = map(list, zip(*[j for i in test.values() for j in i]))

print(xs)
[81, 78, 80, 65, 88, 81]

print(ys)
[90, 90, 80, 78, 81, 88]

However, I recommend itertools.chain because it has been shown to outperform nested list comprehensions, comprehensively (...hah).

like image 93
cs95 Avatar answered Mar 20 '23 20:03

cs95


Another approach is to use reduce method by passing a lambda expression as first argument.

from functools import reduce
xs, ys = zip(*reduce(lambda x, y : x + y, test.values()))

A faster way to do the reduce version could be using concat operator.

xs, ys = zip(*reduce(operator.concat, test.values()))
like image 40
Mihai Alexandru-Ionut Avatar answered Mar 20 '23 21:03

Mihai Alexandru-Ionut