초보자를 위한 파이썬: 리스트 중복 제거 방법

目次

1. Python에서 리스트의 중복을 제거해야 하는 이유

Python에서 리스트의 중복을 제거하는 것은 많은 상황에서 중요합니다. 특히 대규모 데이터셋을 다룰 때, 데이터의 고유성을 보장하고 효율적인 처리를 가능하게 하는 것이 필수적입니다.

리스트의 중복을 제거해야 하는 이유

  1. 데이터 분석의 정확성 향상 데이터 분석에서 중복 레코드는 정확한 결과를 얻는 것을 방해할 수 있습니다. 예를 들어, 판매 데이터나 설문 집계의 중복은 잘못된 결론으로 이어질 수 있습니다.
  2. 데이터베이스 통합 Python에서 데이터베이스로 데이터를 가져올 때, 고유 키의 중복 값은 오류를 발생시킵니다. 미리 Python에서 중복을 제거하면 데이터 처리가 원활해집니다.
  3. 처리 효율성 향상 불필요하게 큰 데이터 크기는 메모리와 처리 시간에 부담을 줍니다. 특히 대규모 데이터셋에서 중복 제거는 전체 시스템 성능을 향상시킬 수 있습니다.

중복 제거의 전형적인 시나리오

  • 데이터 정제: 웹 스크래핑으로 얻은 데이터를 정리할 때.
  • 중복 감지: 제품 재고 목록이나 사용자 등록 데이터에서 중복을 찾을 때.
  • 배열 작업: 특정 리스트 조작 중에 중복 항목을 제거하고 싶을 때.

이 기사의 목적

이 기사는 Python에서 리스트의 중복을 제거하는 방법을 기본 기법부터 고급 예제까지 설명합니다. 초보자를 위한 간단한 접근법부터 순서를 유지하고 성능을 고려한 방법까지 다루며, 독자들이 자신의 필요에 맞는 최적의 방법을 선택할 수 있도록 돕습니다.

Ad

2. set을 사용해 리스트에서 중복 제거하기

Python에서 리스트의 중복을 제거하는 가장 기본적인 방법은 set을 사용하는 것입니다. set은 중복을 허용하지 않는 Python의 내장 데이터 타입입니다. 이 특성을 활용하면 리스트에서 중복을 쉽게 제거할 수 있습니다.

기본 코드 예제

다음 코드는 리스트에서 중복 요소를 제거하고 고유 요소만 포함된 리스트를 생성하는 방법을 보여줍니다.

# Original list
my_list = [1, 2, 2, 3, 4, 4, 5]

# Remove duplicates using set
unique_list = list(set(my_list))

print(unique_list)  # Result: [1, 2, 3, 4, 5]

실행 결과 및 설명

  • 입력 : [1, 2, 2, 3, 4, 4, 5]
  • 출력 : [1, 2, 3, 4, 5] (중복 요소 24가 제거됨)

이 코드에서 리스트를 set 타입으로 변환하면 중복이 자동으로 제거됩니다. 그 후 list() 함수를 사용해 set을 다시 리스트로 변환합니다.

set 사용의 장점

  1. 간단하고 직관적 간결한 코드로 구현할 수 있어 초보자가 이해하기 쉽습니다.
  2. 빠름 set의 특성 덕분에 중복 제거가 효율적으로 수행됩니다.

set 사용 시 주의사항

원본 리스트의 순서가 유지되지 않음 아래 예제를 참조하세요.

# Original list
my_list = [4, 3, 4, 2, 1]

# Remove duplicates using set
unique_list = list(set(my_list))

print(unique_list)  # Result: [1, 2, 3, 4]

이 결과에서 보듯이, set을 사용하면 리스트의 요소가 임의로 재정렬될 수 있습니다. 따라서 순서가 중요한 경우 다른 접근법을 고려해야 합니다.

set을 사용할 때

  • 순서가 중요하지 않을 때.
  • 간단하고 빠른 해결책이 필요할 때.

다음 섹션에서는 순서를 유지하면서 중복을 제거하는 방법을 자세히 설명합니다.

Ad

3. 순서를 유지하면서 중복 제거하기

Python에서 리스트의 중복을 제거하면서 순서를 유지하고 싶다면 set만으로는 부족합니다. 따라서 여기서는 순서를 그대로 유지하면서 중복을 제거할 수 있는 대안 방법을 소개합니다. 이 섹션에서는 dict.fromkeys()OrderedDict 사용법을 설명합니다.

dict.fromkeys() 사용하기

Python 3.6 이후부터 딕셔너리(dict)는 삽입 순서를 유지합니다. 이 특성을 활용하면 원본 순서를 유지하면서 리스트의 중복을 제거할 수 있습니다.

예제 코드

# Original list
my_list = [4, 3, 4, 2, 1]

# Remove duplicates using dict.fromkeys()
unique_list = list(dict.fromkeys(my_list))

print(unique_list)  # Result: [4, 3, 2, 1]

결과 및 설명

  • 입력 : [4, 3, 4, 2, 1]
  • 출력 : [4, 3, 2, 1] 이 코드는 dict.fromkeys()를 사용해 리스트 요소들을 딕셔너리 키로 저장합니다. 딕셔너리 키는 중복을 허용하지 않으므로 중복이 자동으로 제거됩니다. 그런 다음 딕셔너리 키를 다시 리스트로 변환하면 순서가 보존된 결과를 얻을 수 있습니다.

장점

  1. 순서가 보존됩니다 원본 리스트의 순서를 유지하면서 중복을 제거할 수 있습니다.
  2. 간결한 코드 dict.fromkeys()만 사용하면 순서 보존과 중복 제거를 동시에 달성할 수 있습니다.

단점

  • 딕셔너리의 내부 동작을 이해하지 못한다면 초보자에게 다소 어려울 수 있습니다.

OrderedDict 사용하기

다른 방법으로는 collections 모듈의 OrderedDict를 사용하는 것이 있습니다. 이 방법 역시 리스트에서 중복을 제거하면서 순서를 유지할 수 있습니다.

예제 코드

from collections import OrderedDict

# Original list
my_list = [4, 3, 4, 2, 1]

# Remove duplicates using OrderedDict
unique_list = list(OrderedDict.fromkeys(my_list))

print(unique_list)  # Result: [4, 3, 2, 1]

결과 및 설명

일반 딕셔너리와 마찬가지로 OrderedDict는 중복 키를 허용하지 않으며 삽입된 순서를 보존합니다. dict.fromkeys()와 유사하지만 Python 버전에 관계없이 안정적으로 동작합니다.

장점

  1. 높은 호환성 Python 3.6 이전 버전에서도 순서를 보존합니다.
  2. 높은 신뢰성 OrderedDict는 의도적으로 순서 보존을 지원하므로 보다 확실한 방법입니다.

단점

  • 표준 라이브러리에서 가져와야 합니다.
  • dict.fromkeys()에 비해 약간 복잡합니다.

성능 비교

아래는 dict.fromkeys()OrderedDict를 사용할 때의 성능 비교입니다.

코드 예시

import time
from collections import OrderedDict

# Large dataset
large_list = [i for i in range(100000)] + [i for i in range(100000)]

# Performance of dict.fromkeys()
start = time.time()
unique_list1 = list(dict.fromkeys(large_list))
print(f"dict.fromkeys() processing time: {time.time() - start:.6f} seconds")

# Performance of OrderedDict
start = time.time()
unique_list2 = list(OrderedDict.fromkeys(large_list))
print(f"OrderedDict processing time: {time.time() - start:.6f} seconds")

결과 (예시)

dict.fromkeys() processing time: 0.014561 seconds
OrderedDict processing time: 0.018437 seconds
  • dict.fromkeys()가 약간 더 빠릅니다.
  • OrderedDict는 호환성이나 신뢰성이 중요한 경우에 유용합니다.

메서드를 사용할 때

  1. 순서가 중요한 경우.
  2. 순서 보존과 중복 제거를 동시에 달성하고 싶을 때.
  3. Python 버전이나 향후 호환성을 고려할 때.
Ad

4. 리스트에서 중복을 제거하는 고급 방법

Python은 기본 중복 제거 기법으로는 처리하기 어려운 더 복잡한 경우를 다룰 수 있습니다. 이 섹션에서는 2차원 리스트와 조건부 중복 제거에 대해 설명합니다.

2차원 리스트에서 중복을 제거하는 방법

2차원 리스트(리스트가 리스트를 포함하는 구조)에서는 일반적인 set이나 dict.fromkeys()를 바로 사용할 수 없습니다. 이는 리스트가 가변(변경 가능)하기 때문에 set의 키나 딕셔너리 키로 사용할 수 없기 때문입니다.

방법: 튜플 사용

리스트를 일시적으로 튜플로 변환하면 set을 활용해 2차원 리스트에서도 중복을 제거할 수 있습니다.

예제 코드

# Original two-dimensional list
nested_list = [[1, 2], [3, 4], [1, 2]]

# Remove duplicates
unique_list = [list(x) for x in set(tuple(x) for x in nested_list)]

print(unique_list)  # Result: [[1, 2], [3, 4]]

실행 결과 및 설명

  • 입력 : [[1, 2], [3, 4], [1, 2]]
  • 출력 : [[1, 2], [3, 4]]

이 코드에서는 2차원 리스트의 각 내부 리스트를 일시적으로 튜플로 변환한 뒤 set에 저장하여 중복을 제거합니다. 그 후 결과를 다시 리스트로 변환합니다.

장점

  • 간결한 방식으로 2차원 리스트의 중복을 제거할 수 있습니다.
  • 원래 구조(리스트)로 다시 변환할 수 있어 유연하게 사용할 수 있습니다.

단점

  • 내부 리스트가 더 깊게 중첩되거나 복잡한 경우 이 방법을 적용하기 어려울 수 있습니다.

조건부 중복 제거 수행 방법

리스트 요소에 기반한 특정 조건이 충족될 때만 중복을 제거할 수도 있습니다. 예를 들어, 특정 키의 값이 동일한 경우 사전 리스트에서 중복을 제거하는 상황을 생각해 볼 수 있습니다.

예시 코드

아래 예시는 "id" 키의 값이 동일한 경우 사전 리스트의 중복을 제거하여 사전이 고유하도록 합니다.

# Original list (list of dictionaries)
data_list = [
    {"id": 1, "name": "Alice"},
    {"id": 2, "name": "Bob"},
    {"id": 1, "name": "Alice"},
    {"id": 3, "name": "Charlie"}
]

# Remove duplicates based on the id key
unique_list = list({item["id"]: item for item in data_list}.values())

print(unique_list)
# Result: [{'id': 1, 'name': 'Alice'}, {'id': 2, 'name': 'Bob'}, {'id': 3, 'name': 'Charlie'}]

실행 결과 및 설명

  • 입력 : [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}, {"id": 1, "name": "Alice"}, {"id": 3, "name": "Charlie"}]
  • 출력 : [{'id': 1, 'name': 'Alice'}, {'id': 2, 'name': 'Bob'}, {'id': 3, 'name': 'Charlie'}]

이 코드에서는 사전 리스트를 일시적으로 키가 가능한 형태로 변환해 중복을 제거합니다. 이후 values() 메서드를 사용해 원래 데이터 구조를 리스트로 복원합니다.

장점

  • 임의의 조건에 기반한 유연한 중복 제거가 가능합니다.
  • 사전뿐만 아니라 다른 복잡한 데이터 구조에도 적용할 수 있습니다.

단점

  • 코드가 다소 복잡할 수 있어 초보자에게는 어려울 수 있습니다.

사용 사례: 데이터 분석에서 중복 제거

이러한 방법은 데이터 분석 및 데이터 정제 작업에 특히 유용합니다. 예를 들어 다음과 같은 상황에 적용할 수 있습니다.

  • 동일한 사용자 ID를 가진 중복 레코드 제거
  • 여러 데이터 소스를 병합할 때 발생하는 중복 정리
  • 특정 컬럼 값에 기반한 고유 데이터셋 생성

고급 방법을 사용해야 할 때

  1. 2차원 리스트 또는 사전 리스트의 중복을 제거할 때
  2. 특정 조건에 따라 중복을 제거해야 할 때
  3. 분석을 위한 전처리 단계에서 데이터를 준비하고 정제할 때
Ad
RUNTEQ(ランテック)|超実戦型エンジニア育成スクール

5. 성능 비교

Python에서 리스트의 중복을 제거할 때, 사용된 방법에 따라 성능(실행 속도 및 메모리 사용량)이 달라집니다. 이 섹션에서는 대표적인 방법들의 성능을 비교하고 적절한 사용 사례를 고려합니다.

비교 대상 방법 및 평가 기준

비교 대상 방법

  1. set을 이용한 방법
  2. dict.fromkeys()를 이용한 방법
  3. OrderedDict를 이용한 방법

평가 기준

  • 처리 속도 (데이터 크기에 따른 실행 시간)
  • 메모리 사용량 (대량 데이터 처리 시 효율성)

실제 코드로 수행한 벤치마크 테스트

각 방법의 실행 속도를 측정하기 위해 다음 코드를 사용합니다.

벤치마크 코드 예시

import time
from collections import OrderedDict

# Creating a large dataset
large_list = [i for i in range(100000)] + [i for i in range(50000)]

# When using set
start_time = time.time()
unique_set = list(set(large_list))
print(f"set processing time: {time.time() - start_time:.6f} seconds")

# When using dict.fromkeys()
start_time = time.time()
unique_dict = list(dict.fromkeys(large_list))
print(f"dict.fromkeys() processing time: {time.time() - start_time:.6f} seconds")

# When using OrderedDict
start_time = time.time()
unique_ordered_dict = list(OrderedDict.fromkeys(large_list))
print(f"OrderedDict processing time: {time.time() - start_time:.6f} seconds")

예시 벤치마크 결과

아래는 대규모 데이터셋(150,000개 이상의 요소)으로 실행 시간 결과를 측정한 예시입니다:

set processing time: 0.012345 seconds
dict.fromkeys() processing time: 0.016789 seconds
OrderedDict processing time: 0.018234 seconds

결과에 대한 논의

  1. set 가장 빠르고 효율적입니다. 순서를 유지할 필요가 없을 때 적합합니다.
  2. dict.fromkeys() set보다 약간 느리지만, 순서를 유지해야 할 때 매우 유용합니다.
  3. OrderedDict 실행 속도는 dict.fromkeys()와 거의 동일하지만, Python 3.6 이전 버전과의 호환성이 필요할 때 사용합니다.

메모리 사용량 비교

아래는 각 방법의 메모리 효율성을 간략히 비교한 내용입니다.

MethodMemory efficiencyCharacteristics
Using setHighOptimal for very large data sizes.
Using dict.fromkeys()ModerateGood balance of order preservation and efficiency.
Using OrderedDictSomewhat lowUsed in scenarios that prioritize compatibility.

적절한 방법을 선택하기 위한 핵심 포인트

set을 선택할 때

  • 데이터 순서가 중요하지 않을 때
  • 실행 속도를 우선시하고 싶을 때
  • 대규모 데이터를 처리할 때

dict.fromkeys()를 선택할 때

  • 순서를 유지하면서 중복을 제거하고 싶을 때
  • 간단한 코드를 선호할 때

OrderedDict를 선택할 때

  • 순서를 유지해야 하지만 Python 3.6 이전 버전에서도 동작해야 할 때
  • 오래된 코드나 레거시 시스템을 다룰 때

실용적인 선택 옵션

실제 상황에 따라 다음과 같이 선택할 수 있습니다:

  1. 데이터 정제 시 속도 우선 : set
  2. 데이터 분석 시 순서 유지 : dict.fromkeys()
  3. 호환성이 필요한 장기 프로젝트 : OrderedDict
Ad

6. 자주 묻는 질문 (FAQ)

이 섹션에서는 Python에서 리스트의 중복을 제거할 때 독자들이 흔히 가질 수 있는 질문에 답변합니다. 각 질문은 실제 프로그램과 실용적인 예시를 기반으로 설명합니다.

1. 왜 set을 사용하면 순서가 유지되지 않나요?

set은 순서를 보존하지 않는 데이터 구조입니다.
set은 중복을 허용하지 않지만 정렬 정보를 유지하지 않는 Python 내장 자료형 중 하나입니다. 따라서 원본 리스트의 순서를 유지해야 한다면 dict.fromkeys()OrderedDict 등을 사용해야 합니다.

해결 방법

# Preserve order using dict.fromkeys()
my_list = [4, 3, 4, 2, 1]
unique_list = list(dict.fromkeys(my_list))
print(unique_list)  # Result: [4, 3, 2, 1]

2. 2차원 리스트에서 순서를 유지하면서 중복을 제거할 수 있나요?

네, 가능합니다. 하지만 2차원 리스트는 리스트 안에 리스트가 들어 있는 구조이므로 set을 바로 사용할 수 없습니다. 대신 일시적으로 튜플로 변환하여 처리할 수 있습니다.

해결 방법

아래는 순서를 유지하면서 2차원 리스트의 중복을 제거하는 예시입니다.

# Original two-dimensional list
nested_list = [[1, 2], [3, 4], [1, 2], [5, 6]]

# Remove duplicates while preserving order
unique_list = []
[unique_list.append(x) for x in nested_list if x not in unique_list]

print(unique_list) # 결과: [[1, 2], [3, 4], [5, 6]]

3. 대규모 데이터셋에서 중복을 효율적으로 제거하려면 어떻게 해야 하나요?

대규모 데이터셋을 다룰 때는 set을 사용하는 것이 가장 효율적입니다. set은 내부적으로 해시 테이블을 사용해 요소를 빠르게 검색하고 저장할 수 있습니다.

해결 방법

# Large dataset
large_list = [i for i in range(100000)] + [i for i in range(50000)]

# Remove duplicates using set
unique_list = list(set(large_list))
print(len(unique_list))  # Result: 100000 (number of unique elements)

주의사항

  • 순서가 보존되지 않으므로, 순서가 중요하다면 다른 방법을 고려하세요.
  • 메모리 사용량이 과도해지면 메모리 효율적인 접근 방식을 고려하세요.

4. 리스트의 일부를 기준으로 중복을 제거할 수 있나요?

네, 가능합니다. 리스트가 딕셔너리 요소들로 구성되어 있다면 특정 키를 기준으로 고유 값을 추출할 수 있습니다.

해결책

# List of dictionaries
data_list = [
    {"id": 1, "name": "Alice"},
    {"id": 2, "name": "Bob"},
    {"id": 1, "name": "Alice"},
    {"id": 3, "name": "Charlie"}
]

# Remove duplicates based on the id key
unique_list = list({item["id"]: item for item in data_list}.values())

print(unique_list)
# Result: [{'id': 1, 'name': 'Alice'}, {'id': 2, 'name': 'Bob'}, {'id': 3, 'name': 'Charlie'}]

5. Python 버전 간 호환성을 신경 써야 하나요?

Python 3.6부터 dict가 순서를 보존합니다. 따라서 dict.fromkeys()를 사용할 때 자신의 Python 버전에 유의해야 합니다. Python 3.5 이하에서 순서를 보존해야 한다면 OrderedDict를 사용해야 합니다.

해결책 (Python 3.5 및 이전 버전용)

from collections import OrderedDict

# Preserve order using OrderedDict
my_list = [4, 3, 4, 2, 1]
unique_list = list(OrderedDict.fromkeys(my_list))
print(unique_list)  # Result: [4, 3, 2, 1]

6. 중복 제거가 제대로 작동하지 않을 때 가능한 원인은 무엇인가요?

중복 제거가 제대로 작동하지 않을 경우 다음을 확인하세요:

  1. 리스트 내 가변 요소 타입 리스트와 딕셔너리는 set의 키로 사용할 수 없으며, 이는 오류를 일으킬 수 있습니다. 필요하다면 튜플로 변환하세요.
  2. Python 버전 호환성 사용 중인 메서드가 현재 Python 버전에서 지원되는지 확인하세요.
  3. 조건 지정 오류 특정 조건에 따라 중복을 제거하려는 경우, 조건이 올바르게 지정되지 않았을 수 있습니다.

FAQ 요약

  • 순서를 보존하고 싶다면: dict.fromkeys() 또는 OrderedDict를 사용하세요.
  • 대규모 데이터셋을 효율적으로 처리하려면: set을 사용하세요.
  • 조건부 중복 제거: 딕셔너리나 리스트 컴프리헨션을 사용하세요.

이러한 방법들을 이해하고 상황에 맞는 방법을 선택하면 리스트 작업과 관련된 문제를 해결할 수 있습니다.

Ad

7. 요약

Python에서 리스트의 중복을 제거하는 방법은 간단한 것부터 고급 방법까지 다양합니다. 각 방법마다 장단점이 있으므로, 구체적인 요구와 상황에 맞는 최적의 접근 방식을 선택하는 것이 중요합니다.

기본 방법

set을 이용한 방법은 가장 간단하고 빠른 접근법입니다. 다음과 같은 특징이 있습니다:

  • 장점: 코드가 짧고 실행 속도가 빠릅니다.
  • 단점: 순서가 보존되지 않습니다.
  • 사용 사례: 순서가 중요하지 않거나 대규모 데이터셋을 효율적으로 처리할 때 가장 적합합니다.
    my_list = [1, 2, 2, 3, 4, 4]
    unique_list = list(set(my_list))
    print(unique_list)  # Result: [1, 2, 3, 4]
    

순서 보존 방법

dict.fromkeys()OrderedDict는 순서를 보존하면서 중복을 제거할 수 있습니다. 데이터 순서가 중요한 경우에 적합한 방법입니다.

  • dict.fromkeys() (Python 3.6 이상)
    my_list = [4, 3, 4, 2, 1]
    unique_list = list(dict.fromkeys(my_list))
    print(unique_list)  # Result: [4, 3, 2, 1]
    
  • OrderedDict (Python 3.5 이하에서 사용 가능)
    from collections import OrderedDict
    my_list = [4, 3, 4, 2, 1]
    unique_list = list(OrderedDict.fromkeys(my_list))
    print(unique_list)  # Result: [4, 3, 2, 1]
    

고급 방법

2차원 리스트와 조건부 중복 제거는 보다 복잡한 상황을 처리할 수 있습니다.

  • 2차원 리스트의 경우, 요소를 일시적으로 튜플로 변환하고 set을 사용하는 방법이 있습니다.
  • 딕셔너리 리스트의 경우, 특정 키를 기준으로 중복을 제거할 수 있습니다.
    # Two-dimensional list
    nested_list = [[1, 2], [3, 4], [1, 2]]
    unique_list = [list(x) for x in set(tuple(x) for x in nested_list)]
    print(unique_list)  # Result: [[1, 2], [3, 4]]
    
    # Conditional duplicate removal
    data_list = [
        {"id": 1, "name": "Alice"},
        {"id": 2, "name": "Bob"},
        {"id": 1, "name": "Alice"}
    ]
    unique_list = list({item["id"]: item for item in data_list}.values())
    print(unique_list)  # Result: [{'id': 1, 'name': 'Alice'}, {'id': 2, 'name': 'Bob'}]
    

성능 비교

각 방법의 처리 속도와 메모리 사용량은 데이터 크기와 요구 사항에 따라 달라집니다. 아래는 요약입니다.

MethodSpeedKeeps orderUse cases
Using setFast×Large datasets, when order is not important
Using dict.fromkeys()Medium speedWhen order is important
Using OrderedDictMedium speedPreserves order on older Python versions

방법 선택 가이드

  • 간단하고 빠른 처리가 필요할 경우 : set을 사용합니다.
  • 순서를 유지하고 싶을 경우 : dict.fromkeys() 또는 OrderedDict를 사용합니다.
  • 고급 경우(복잡한 데이터 구조나 조건부 제거) : 튜플 변환이나 리스트 컴프리헨션을 사용합니다.

독자에게 전하는 메시지

이 글에서 소개한 방법을 사용하면 Python에서 리스트의 중복을 효율적으로 제거할 수 있습니다. 데이터의 특성과 목표에 맞는 최적의 접근 방식을 선택하고 실제 프로젝트나 분석에 적용해 보세요.
이 글이 Python을 배우는 사람이나 리스트를 다루어야 하는 모든 분들에게 도움이 되길 바랍니다. 추가 질문이나 구체적인 사례가 있으면 언제든지 댓글과 피드백을 환영합니다!

Ad
年収訴求