Python으로 리스트에서 동일한 요소 제거하기
두 개의 리스트에서 공통 요소를 제거하는 코드를 작성할 때, 의도대로 동작하지 않아 당황하는 경우가 많습니다. 이 문제는 대부분 return 문의 위치와 변수명 오타 때문에 발생합니다.
문제 원인
첫 번째 원인은 return 문의 위치입니다. return 문이 for 블록 내부에 있으면 첫 번째 요소만 처리한 후 함수가 즉시 종료되어 버립니다. 따라서 return 문은 for 블록 바깥, 즉 모든 반복이 끝난 후에 실행되도록 들여쓰기를 조정해야 합니다.
두 번째 원인은 오타입니다. 마지막 print 문에서 remaove_new라고 잘못 작성된 부분을 remove_same으로 수정해야 정상적으로 호출됩니다.
수정된 코드
def remove_same(L1, L2):
L1_copy = L1[:]
for e in L1_copy:
if e in L2:
L1.remove(e)
return L1
L1 = [1,2,3,4]
L2 = [1,2,5,6]
print(remove_same(L1, L2))
실행 결과:
[3, 4]
코드 동작 방식
위 코드가 어떻게 동작하는지 단계별로 살펴보겠습니다.
L1_copy = L1[:]: 슬라이싱을 이용해 원본 리스트의 복사본을 만듭니다. 리스트를 직접 순회하면서 요소를 제거하면 인덱스가 밀려 일부 요소가 건너뛰어지는 버그가 발생할 수 있기 때문입니다.if e in L2: 복사본의 각 요소가 두 번째 리스트에 존재하는지 확인합니다.L1.remove(e): 존재한다면 원본 리스트에서 해당 요소를 제거합니다.return L1: for 블록이 모두 끝난 후 최종 결과를 반환합니다.
결과적으로 [1, 2, 3, 4]와 [1, 2, 5, 6]의 공통 요소인 1과 2가 제거되어 [3, 4]가 출력됩니다.
추가 팁: 더 간단한 대안
리스트 컴프리헨션(list comprehension)을 사용하면 같은 기능을 한 줄로 구현할 수 있습니다.
def remove_same(L1, L2):
return [e for e in L1 if e not in L2]
원본 리스트를 유지할 필요가 없다면 이 방법이 더 간결하고 가독성이 좋습니다. 다만 성능이 중요한 대용량 데이터에서는 L2를 집합(set)으로 변환한 후 멤버십 검사를 수행하면 속도를 크게 향상시킬 수 있습니다.