0
visited_cities = ["New York", "Shanghai", "Munich", "Toyko",
                  "Dubai", "Mexico City", "São Paulo", "Hyderabad"]

for city in visited_cities:
    if len(city) > 5:
        visited_cities.remove(city)
    else:
        continue
    print(visited_cities)

I confirmed that 'Shanghai' is recognized as length greater than 5 using print instead of remove. So why is 'Shanghai' and 'São Paulo' remaining on list while 'New York' 'Munich' 'Mexico City' and 'Hyderabad' are removed?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Jonathan
  • 3
  • 2
  • 2
    Don't change the length of a list while iterating over it... – jonrsharpe May 21 '20 at 21:56
  • sorry, first post. I clearly didn't know how to enter the code AS code! It is returned and indented properly in my IDE. – Jonathan May 21 '20 at 21:59
  • this was part of an assignment (self study) with the instructions: remove city names 5 characters or less from sorted_cities. When I created a new list and appended all cities less than 6 characters it worked fine. So jonrsharpe is that a general practice or the reason it is behaving strangely? – Jonathan May 21 '20 at 22:03
  • 1
    visited_cities[:] = [x for x in visited_cities if len(x) < 6] – Jonathan May 21 '20 at 22:08
  • if any newbie stumbles on this, check out Visualizer to understand why you don't change a list while iterating over it. http://www.pythontutor.com/visualize.html#mode=edit – Jonathan May 21 '20 at 22:28

1 Answers1

2

Adding print(city) at the beginning of the for loop will help with troubleshooting. You can see that you are changing the iterable in your for-loop. This is causing the problem. To solve this, making a copy of the list can help.

visited_cities = ["New York", "Shanghai", "Munich", "Toyko",
                  "Dubai", "Mexico City", "São Paulo", "Hyderabad"]

print([x for x in visited_cities if len(x) < 6])

>>> ['Toyko', 'Dubai']
Rookie
  • 305
  • 2
  • 11
  • I know time wasn't identified as a requirement, but I'm curious if copy() is an unnecessary step. Could do the reverse of what is here. Iterate over the list and append values to a new list that meet the criteria (i.e. len(city) < 6). Is copy/remove more efficient than simply newlist.append(city)? – patmcb May 22 '20 at 02:18
  • 1
    Looking at the answer from Jonathan in the comments, that is the better answer. I will update mine so others use that method. – Rookie May 22 '20 at 02:28