1

I want to remove 'canBeGuessed' list items from the 'sortedList' items. The below code does that:

canBeGuessed = ['A', 'B', 'C']
SORTED_FREQUENCIES = 'ZQXJKVBPYGFWMUCLDRHSNIOATE'
sortedList = list(SORTED_FREQUENCIES)

for letter in SORTED_FREQUENCIES:
    if letter not in canBeGuessed:
        sortedList.remove(letter)

print(f"New sorted List: {sortedList}")

Output: New sorted List: ['B', 'C', 'A']

My question is, why doesn't this work when you change SORTED_FREQUENCIES to sortedList in the for loop? 'letter' in the for loop is the same type/output for both variables:

canBeGuessed = ['A', 'B', 'C']
SORTED_FREQUENCIES = 'ZQXJKVBPYGFWMUCLDRHSNIOATE'
sortedList = list(SORTED_FREQUENCIES)

for letter in sortedList:
    if letter not in canBeGuessed:
        sortedList.remove(letter)

print(f"New sorted List: {sortedList}")

Output: New sorted List: ['Q', 'J', 'V', 'B', 'Y', 'F', 'M', 'C', 'D', 'H', 'N', 'O', 'A', 'E']

I've checked the output and type of 'letter' and they are the same when looping over SORTED_FREQUENCIES and sortedList.

Noctiscreo
  • 13
  • 4
  • In your second code fragment you are modifying a list that you're iterating over. That will invariably not work. You should step through it with your favourite debugger to understand why – DarkKnight Jul 09 '23 at 18:26

3 Answers3

1

here is what is happening

  • The loop starts with the first element, 'Z', at index 0.
  • 'Z' is not in canBeGuessed, so it should be removed. However, the removal of 'Z' shifts all the remaining elements by one position to the left.
  • The loop moves to the next element, 'Q', but the current index (1) no longer corresponds to 'Q'. 'Q' was originally at index 1 but got shifted to index 0 due to the removal of 'Z'.
  • The loop continues with the shifted indices, leading to incorrect comparisons and removals. As a result, elements that should have been removed are skipped.
zoldxk
  • 2,632
  • 1
  • 7
  • 29
1

Removing an entry from the list while iterating over it causes some entries to be skipped, since they take the position of the removed entry. Therefore, when you remove Z, Q takes the position of Z and in the next iteration, X instead of Q will be processed.

Erich Kitzmueller
  • 36,381
  • 5
  • 80
  • 102
1

You're mutating the list while you're iterating over it. The first approach worked, because SORTED_FREQUENCIES remained unchanged during the loop, while in the second sortedList gets modified. After the first iteration, Z is removed, and the second iteration skips Q, now at index 0, to X, now at index 1.

A quick solution would be to use list slicing to create a copy of the list:

for letter in sortedList[:]:
    if letter not in canBeGuessed:
        sortedList.remove(letter)
B Remmelzwaal
  • 1,581
  • 2
  • 4
  • 11