Hound
Hound

Reputation: 972

Removing dictionaries from list with for loop

I have this sample list of dictionaries below. I want to know why the below code will only loop over two values in the list? Why does it not loop over every value in the list?

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

for site_dict in updated_list_of_site_dicts:
    if site_dict['status'] == 'ready':
        print site_dict['site'] + " is ready"
        updated_list_of_site_dicts.remove(site_dict)
        print updated_list_of_site_dicts

Upvotes: 1

Views: 53

Answers (2)

Memduh
Memduh

Reputation: 866

It loops only twice because remove() method causes list indexes to shift.

If you want to loop the list and remove elements you should iterate the list in reverse order. Such as;

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

for i in range(len(updated_list_of_site_dicts) - 1, -1, -1): 
    site_dict = updated_list_of_site_dicts[i]
    if site_dict['status'] == 'ready':
        print site_dict['site'] + " is ready"
        updated_list_of_site_dicts.remove(site_dict)
        print updated_list_of_site_dicts

Also, if you only want to remove elements you can use filter too.

>>> updated_list_of_site_dicts = [{'site': 'living', 'status': 'ready' }, {'site': 'keg', 'status': 'ready' }, {'site': 'box', 'status': 'ready' }, {'site': 'wine', 'status': 'ready' }, {'site': 'can', 'status': 'not_ready' }]
>>> updated_list_of_site_dicts = filter(lambda x: x['status'] != 'ready', updated_list_of_site_dicts)
>>> updated_list_of_site_dicts
[{'status': 'not_ready', 'site': 'can'}]

Upvotes: 1

Brad Solomon
Brad Solomon

Reputation: 40918

Use list comprehension to update instead:

updated_list_of_site_dicts = [d for d in updated_list_of_site_dicts 
                              if d['status'] != 'ready']

Note that in your current example, you have all 'ready' so you'll get an empty list. Here's an example where one status isn't ready:

updated_list_of_site_dicts = [{'site': 'living', 'status': 'ready' }, 
                              {'site': 'keg', 'status': 'ready' }, 
                              {'site': 'box', 'status': 'ready' }, 
                              {'site': 'wine', 'status': 'NOT READY' }]

for d in updated_list_of_site_dicts:
    if d['status'] == 'ready':
        print(d['site'] + " is ready")
living is ready
keg is ready
box is ready

updated_list_of_site_dicts = [d for d in updated_list_of_site_dicts 
                              if d['status'] != 'ready']
print(updated_list_of_site_dicts)
[{'site': 'wine', 'status': 'NOT READY'}]

Upvotes: 1

Related Questions