[Python] Repl.it 오류 - Deleting Elements From List

rang-dev·2020년 5월 27일
0

Input으로 주어진 리스트에서 홀수는 전부 지우고 짝수만 남은 리스트를 리턴해주세요.
리스트의 요소들은 전부 숫자값이고 총 요소 수는 5개 입니다.

Error

def remove_odd_numbers(numbers):
  for i in range(len(numbers)):
    if numbers[i]%2!=0:
      del numbers[i]
      
  print(numbers)
  
  
remove_odd_numbers([1,2,3,4,5])
>   
Traceback (most recent call last):
  File "python", line 9, in <module>
  File "python", line 3, in remove_odd_numbers
IndexError: list index out of range

list의 index가 범위를 벗어났다. 그 이유는 numbers를 루프로 돌리면서 요소를 삭제하기 때문에 len이 계속 변하기 때문이다.

len: 5, i= 0
len: 4, i= 1
len: 3, i= 2
len: 2, i= 3

for문이 돌아갈때마다 len은 줄어드는 반면 i는 증가하기 때문에 나중에는 i가 len보다 더 커지게 된다. 따라서 IndexError가 발생한다.

First Trial

def remove_odd_numbers(numbers):
  numbers2 = numbers.copy()
  for i in range(len(numbers)):
    if numbers2[i]%2!=0:
      del numbers2[i]
      
  print(numbers2)

remove_odd_numbers([1,2,3,4,5])

그럼 len이 유지될 수 있도록 copy본을 만들어서 거기서 요소를 삭제하면 어떨까?라고 생각했지만 이역시 IndexError가 발생했다.

왜냐하면 numbers에서 돌아가는 i는 계속 올라가지만 해당 index를 numbers2에서 삭제해주어야하는데 여기서는 요소가 삭제되면서 len이 감소하므로 IndexError가 발생하게 되는 것이다.

len_numbers: 5, len_numbers2: 5, i: 0
len_numbers: 5, len_numbers2: 4, i: 1
len_numbers: 5, len_numbers2: 3, i: 2
len_numbers: 5, len_numbers2: 2, i: 3

Second Trial

i는 증가하는데 len은 감소하기때문에 충돌한다 --> 그럼 i와 len이 동시에 줄어들면?

def remove_odd_numbers(numbers):
  for i in range(len(numbers)-1, -1, -1):
    if numbers[i]%2!=0:
      del numbers[i]
      
  print(numbers)
  
remove_odd_numbers([1,2,3,4,5])
> [2, 4]

오류가 발생하지 않았다. i는 -1씩 줄어들고 len은 홀수가 있을때만 줄어들기 때문에 i가 줄어드는 속도보다 느려서 항상 i < len이 된다. numbers에서 i가 지나가는 부분을 *로 표시해보았다.

len_numbers=5, i=4, numbers=[1, 2, 3, 4, *5]
len_numbers=4, i=3, numbers=[1, 2, 3, *4]
len_numbers=4, i=2, numbers=[1, 2, *3, 4]
len_numbers=3, i=1, numbers=[1, *2, 4]
len_numbers=3, i=0, numbers=[*1, 2, 4]

i가 오름차순이었을때는 요소를 지우고 다음 index로 이동하기 때문에 지워진 index의 다음 index들에 영향을 미쳤었는데 내림차순으로 이동하니 뒤에서 삭제된 요소들은 앞의 index들에 영향을 끼치지 않는다.

Model Solution

my_list     = [int(s) for s in input().split()]
odd_numbers = [ ]

## 먼저 홀수값들을 골라내서 리스트를 만들고
for element in my_list:
    if (element % 2) == 1:
        odd_numbers.append(element)

## 홀수값들을 하나 하나 기존 리스트에서 지워준다
for odd_number in odd_numbers:
    my_list.remove(odd_number)

print(my_list)
profile
지금 있는 곳에서, 내가 가진 것으로, 할 수 있는 일을 하기 🐢

0개의 댓글