There's a pretty easy trick to nested comprehensions.
Just write the loop as normal:
for name, values in map_of_values.items():
for value in values:
yield name, value
Then concatenate everything on one line:
[for name, values in map_of_values.items(): for value in values: yield name, value]
Then move the yield to the very start, wrap it in parentheses (if necessary), and remove colons:
[(name, value) for name, values in map_of_values.items() for value in values]
And that's your comprehension.
Maybe this makes more sense if you're reading it on a wide screen:
[ for name, values in map_of_values.items(): for value in values: yield name, value]
^^^^^^^^^^^^^^^^^
/------------------------------------------------------------------------------/
vvvvvvvvvvvvv
[(name, value) for name, values in map_of_values.items() for value in values ]
I wrote it on one line to make the example make sense, but most Python comprehensions are plenty readable if they're split into many lines:
new_list = [
(name, value)
for name, values in map_of_values.items()
for value in values
]
The normal loop needs either a yield (which means you have to put it inside a generator function, and then call and list() the generator), or you have to make a list and keep appending things into it, which looks worse.
agree on the appending to a list. that’s an obvious code smell of “i didn’t know how to do idiomatic python iteration when i wrote this”.
i disagree that the format of the list comprehension above is easier to read than a generator function personally.
however, it’s definitely easier to read than most multi-loop list comprehensions i’ve seen before (even with HN formatting sticking the x.items() on a new line :/ ).
so i see what you’re getting at. it is definitely better. i just find it weird that the the tuple definition comes before the thing i’m doing to get the tuple. sometimes i have to think “backwards” while reading it. i don’t like thinking while reading code. it makes it harder to read the code. and that “thinking” effect increases when the logic is complicated.
Wow, this is nice. I've been doing Python for quite a few years and whenever I needed a nested comprehension I'd always have to go to my cheatsheet. Now that I've seen how it's composed that's one less thing I'll need to lookup again. Thank you.
It's a fairly clunky idiom and there's no reason to use it if you prefer more explicit code.
I can see the attraction for terse solutions, but even the name is questionable. ("Comprehension?" Of what? It's not comprehending anything. It's a filter/processor.)
Just write the loop as normal:
Then concatenate everything on one line: Then move the yield to the very start, wrap it in parentheses (if necessary), and remove colons: And that's your comprehension.Maybe this makes more sense if you're reading it on a wide screen: