1

I would like to move elements from one list to another based on a separate boolean list. I attempted the following pattern but pop at an early index shortens the list and I run into an IndexError at later elements.

list_1 = [1, 2, 3, 4]
list_2 = []
to_move = [True, False, False, True]

for idx, element in enumerate(to_move):
  if element:
    list_2.append(list_1.pop[idx]) #at element 4 (index 3), list_1 has already had its indices changed and cannot pop based on index 3

Another way might be to remove elements AFTER initial move, but I currently run into the same problem.

list_1 = [1, 2, 3, 4]
list_2 = []
to_move = [True, False, False, True]

for idx, element in enumerate(to_move):
  if element:
    list_2.append(list_1[idx])
for idx, element in enumerate(to_move):
  if element:
     list_1.remove(idx) # is there a way to remove all elements at once based on index?

If there is a way to move/remove all elements in a list at once (ie. without losing index spot in list), thus avoiding an IndexError?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
Shaner
  • 73
  • 1
  • 10
  • Have you considered removing items from the list starting from the end of the list? – mkrieger1 Feb 24 '22 at 23:49
  • 1
    Does this answer your question? [How to remove items from a list while iterating?](https://stackoverflow.com/questions/1207406/how-to-remove-items-from-a-list-while-iterating) – mkrieger1 Feb 24 '22 at 23:51

1 Answers1

1

Generally speaking, you shouldn't try to modify a list as you're iterating over it, as the memory is shifting while you're trying to access it (the mapping between the elements in list_1 and to_move may not be easily retained if you remove elements from list_1 as well).

Instead, use a list comprehension:

list_1 = [1, 2, 3, 4]
to_move = [True, False, False, True]

list_2 = [elem for index, elem in enumerate(list_1) if to_move[index]]
list_1 = [elem for index, elem in enumerate(list_1) if not to_move[index]]

print(list_1, list_2) # Prints [2, 3] [1, 4]
BrokenBenchmark
  • 18,126
  • 7
  • 21
  • 33
  • 1
    Just in case you need to retain the original `list_1` object (maybe you are trying to remove items in-place from a function argument), do a slice assignment: `list_1[:] = [...]`. – chepner Feb 25 '22 at 00:56
  • 1
    This was exactly what I needed, thank you both! – Shaner Feb 28 '22 at 13:03