새소식

반응형
Python/알고리즘

파이썬 리스트 순회 중 요소 제거(반복문 도중에 멈춤): 함정과 해결책

  • -
반응형

파이썬에서 리스트를 다룰 때 흔히 마주치는 문제 중 하나는 리스트를 순회하면서 동시에 요소를 제거하는 상황입니다. 이런 작업이 예상치 못한 결과를 낳는 경우가 많은데, 오늘은 이 문제와 그 해결 방법을 알아보겠습니다.

python

문제가 있는 코드

다음 코드를 봐주세요:

def remove_max_values(values):
    if not values: return
    max_val = max(values)
    for i, v in enumerate(values):
        if v == max_val:
            values.pop(i)
            result.append(v)
    return result

# 테스트
values = [5, 5, 4, 3, 5, 2]
result = []
print("원래 리스트:", values)
remove_max_values(values)
print("결과:", result)
print("남은 값들:", values)

이 함수는 리스트에서 최대값들을 찾아 제거하고 다른 리스트에 추가하려 합니다. 하지만 이 코드를 실행하면 예상과 다른 결과가 나옵니다:

원래 리스트: [5, 5, 4, 3, 5, 2]
결과: [5, 5]
남은 값들: [5, 4, 3, 2]

 

예상과 달리 모든 5가 제거되지 않았습니다.

 

왜 이런 일이 일어날까요?

이 문제는 리스트를 순회하면서 동시에 요소를 제거하기 때문에 발생합니다. pop() 메소드로 요소를 제거하면 리스트 크기가 변하고, 이는 반복 중에 예상치 못한 결과를 낳습니다.

예를 들어, [5, 5, 4, 3] 리스트를 순회한다고 가정해 봅시다:

  1. 첫 번째 5를 제거합니다.
  2. 리스트는 [5, 4, 3]이 됩니다.
  3. 인덱스가 1로 증가하여 4를 가리킵니다.
  4. 두 번째 5를 건너뛰게 됩니다.
반응형

어떻게 고칠 수 있을까요?

이 문제를 해결하기 위한 몇 가지 방법이 있습니다:

  1. 리스트를 거꾸로 순회합니다.
  2. 제거할 인덱스를 따로 저장한 후 한 번에 제거합니다.
  3. 리스트 컴프리헨션으로 새 리스트를 만듭니다.

해결책

이 문제를 해결하기 위해 다음과 같이 코드를 수정할 수 있습니다:

def remove_max_values(values):
    if not values:
        return []
    
    max_val = max(values)
    to_remove = []
    
    for i, v in enumerate(values):
        if v == max_val:
            to_remove.append(i)
    
    result = []
    # 큰 인덱스부터 제거하여 앞의 인덱스에 영향을 주지 않도록 함
    for i in sorted(to_remove, reverse=True):
        result.append(values.pop(i))
    
    return result

# 테스트
values = [5, 5, 4, 3, 5, 2]
print("원래 리스트:", values)
result = remove_max_values(values)
print("결과:", result)
print("남은 값들:", values)

이 수정된 코드를 실행하면 다음과 같은 결과가 나옵니다:

원래 리스트: [5, 5, 4, 3, 5, 2]
결과: [5, 5, 5]
남은 값들: [4, 3, 2]

이제 모든 최대값(5)이 올바르게 제거되고 결과 리스트에 추가되었습니다.

설명

이 해결책이 작동하는 이유는 다음과 같습니다:

  1. 먼저 모든 최대값의 인덱스를 찾아 to_remove 리스트에 저장합니다.
  2. 그 다음, 이 인덱스들을 큰 순서대로 정렬합니다.
  3. 큰 인덱스부터 요소를 제거하면, 앞쪽 인덱스의 요소들이 영향을 받지 않습니다.

이 방식을 사용하면 리스트를 한 번만 순회하면서도 모든 최대값을 정확하게 찾아 제거할 수 있습니다.

결론

리스트를 순회하면서 요소를 제거할 때는 항상 주의가 필요합니다. 이런 상황에서는 리스트의 크기가 변경되어 예상치 못한 결과가 발생할 수 있기 때문입니다. 위에서 제시한 방법을 활용하면 이러한 문제를 피하고 원하는 결과를 얻을 수 있습니다.

파이썬으로 알고리즘을 짜실때 이러한 점을 기억하시면 더욱 안정적이고 예측 가능한 코드를 작성하실 수 있을 것입니다.

 
반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.