1

How could I do the below code with a list comprehension. I have been looking at these examples, but I can't figure it out :|

Python: Removing list element while iterating over list

list_dicts = [{'site': 'living', 'status': 'ready' }, {'site': 'keg', 
'status': 'ready' }, {'site': 'box', 'status': 'ready' }, {'site': 'wine', 
'status': 'not_ready' }]

def call_some_func(m_site_dict):
     print "I executed the 'call_something_function'"

for site in list_dicts[:]:
    if site['status'] == 'ready':
        call_some_func(site)
        list_dicts.remove(site)
Adam Smith
  • 52,157
  • 12
  • 73
  • 112
Hound
  • 932
  • 2
  • 17
  • 26
  • `list_dicts = [{'site': site, 'status': 'ready' if site != 'wine' else 'not_ready'} for site in ['living', 'keg', 'box', 'wine']]`, but note that I would write exactly what you have. – Adam Smith Sep 08 '17 at 23:51
  • 4
    if you mean how would you use a list comprehension in place of the for loop, you wouldn't. List comprehensions are a way concisely create lists, not a drop-in replacement for a for loop. – Adam Smith Sep 08 '17 at 23:53
  • @AdamSmith ah ok, thank you. – Hound Sep 08 '17 at 23:54

1 Answers1

1

It is not a great idea to replace this for loop because you are making a function call with side effects (currently printing). You can use an else clause to construct a new list, which would be more performant (O(1) for append() vs O(n) for del) e.g.:

In []:
new_list_dicts = []
for site in list_dicts:
    if site['status'] == 'ready':
        call_some_func(site)
    else:
        new_list_dicts.append(site)
new_list_dicts

Out[]:
I executed the 'call_something_function'
I executed the 'call_something_function'
I executed the 'call_something_function'

[{'site': 'wine', 'status': 'not_ready'}]

Just as a demonstration (but very bad form) you can do this as a list comprehension but it relies on short-circuiting and the fact the call_some_func() returns None which is considered False:

In []:
[site for site in list_dicts if site['status'] == 'ready' and 
 call_some_func(site) or site['status'] != 'ready']

Out[]:
I executed the 'call_something_function'
I executed the 'call_something_function'
I executed the 'call_something_function'

[{'site': 'wine', 'status': 'not_ready'}]
AChampion
  • 29,683
  • 4
  • 59
  • 75