1

Is it possible to transform loop below in list comprehension? I know this way is more readable, but anyway just wondering..

new_dict = {"Water Lilly": "flower",
               "Swifts": "bird",
               "Callery Pear": "tree",
               "Swallows": "bird",
               "Dahlia": "flower",
               "Tulip": "flower",}

for key, value in new_dict.items():
    print(key+':')
    for val in value:
        print("-" + val)
Ivan
  • 17
  • 3

2 Answers2

1

I think this would work but kinda hard to read :D

x = [(print(key + ":"), [print("-" + val) for val in value]) for key, value in new_dict.items()]

It works like a normal listcomprehension

[do_sth_with_x(x) for x in list]

but your working 2 values

[(do_sth_with_x(x), do_sth_with_y(y)) for x, y in list]

and in the 3th step you add a second list comprehension instead of the do_st_with_y()

there you go there is your listcomp

Geibelt
  • 17
  • 1
  • 7
  • Yea, It works. Looks crazy, but works. Thanks – Ivan Feb 21 '22 at 06:44
  • 1
    You really should not use list-comprehensions purely for side-effects, like printing. – Paul M. Feb 21 '22 at 06:45
  • @PaulM. yeah thats true – Geibelt Feb 21 '22 at 06:48
  • Yea, It was exam task. In the end I submit it yesterday on my way, but still wondering if can be done with other way. – Ivan Feb 21 '22 at 06:49
  • If you want output as List of dictionaries - ```lst = [ {k: v} for k, v in new_dict.items()]``` , if you wanted output as List of lists ```lst = [ [k, v] for k, v in new_dict.items()]``` and then ```print(lst)``` – Rajarshi Ghosh Feb 21 '22 at 07:15
0

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.

srj
  • 9,591
  • 2
  • 23
  • 27