It can be done with a one-liner as suggested in this answer. We can agree that the one liner is hard to read. Another issue with it is that we are using side-effects in the comprehension, which is generally considered a bad practice as well.
List comprehensions are expressions; something that evaluates to a value. As opposed to statements, something that is an imperative directive to the interpreter. print(..)
statements are, well, statements. Take a look at this SO question to learn about the differences.
Purely as an exercise of converting a nested for loop into list comprehension, we can try and tackle this problem from the inside out.
let's start with a simple example.
for i in list1:
do_something(i)
can be converted to [do_something(i) for i in list1
]
but if we have multiple statements, how do we get all of them to execute?
for i in list1:
do_something(i)
do_something_else(i)
we can use a "trick" of python where a tuple is evaluated in order whenever python encounters it.
[(do_something(i), do_something_else(i)) for i in list1]
for key, value in new_dict.items():
do_outer(key)
for val in value:
do_inner(value)
converting the inner loop to List comprehension looks like this
for key, value in new_dict.items():
do_outer(key)
[do_inner(value) for value in value]
next we can try to convert the outer loop
[(inner loop stuff) for key, value in new_dict.items()]
expanding the inner loop stuff
[(do_outer(key), [do_inner(value) for value in value]) for
key, value in new_dict.items()]
We use the tuple trick to club both do_outer
and the inner comprehension inside the outer comprehension.
I think we can all agree that the for loop is simpler to read and understand, and looking at the list comprehension, we have no idea what kind of crazy side-effects do_inner
and do_outer
may cause.