리스트에서 중복된 요소를 제거하는 방법


  • 리스트에서 중복된 요소를 제거하는 방법에는 크게 두 가지가 있다.
1. 자료구조 SET을 이용하는 방법
2. 딕셔너리를 이용하는 방법

첫 번째 방법 - SET() 자료구조 이용


  • 파이썬에서는 중복된 요소를 허용하지 않는 SET 이라는 자료구조가 있다.
nums = [1, 3, 5, 7, 9, 2, 4, 6, 6, 5, 4] 

sets = set(nums) # 결과: {1, 2, 3, 4, 5, 7, 8,  9}

list(sets) # 결과: [1, 2, 3, 4, 5, 7, 8, 9]
  • 중복이 제거된 집합을 생성하고나서, 이를 다시 리스트로 변환하면 중복이 제거된 리스트가 반환된다.

  • 공식 문서를 살펴보면, set()은 순서를 보장하지 않는 컬렉션이며, 중복을 허용하지 않는다고 되어있다.

두 번째 방법 - 딕셔너리를 이용하는 방법


  • 두 번째 방법은 딕셔너리의 키가 고유하다는 특성을 이용하여 중복을 제거하는 것이다.
nums = [1, 3, 5, 7, 9, 2, 4, 6, 6, 5, 4]

list(set(dict.fromkeys(nums))) # 결과: [1, 3, 5, 7, 9, 2, 4, 6]
  • SET을 이용한 방법과 차이점은 중복된 요소를 제거하더라도, 순서를 유지한다는 점이다.

  • 딕셔너리 자료구조는 중복된 키 값이 입력되었을 때 값만 덮어쓰여지고 키 값은 유지하는 특성을 이용한 것이다.

  • fromkeys() 는 반복 가능한 값을 인자로 받아, 키로 사용한다 그리고 그 키 값으로 새로운 딕셔너리 타입을 만드는 것을 확인할 수 있다.
>> nums1 = [1, 3, 5, 7, 9, 2, 4, 6, 6, 5, 4]
>> dict.fromkeys(nums1)
{1: None, 3: None, 5: None, 7: None, 9: None, 2: None, 4: None, 6: None}
  • 사용가능한 버전에는 키만 인자로 받는 버전과, 키와 값을 둘다 받는 버전이 있는데 인자로 키만 주어질 경우 키 값만 생성되고 키에 대한 값들은 모두 None으로 설정된다.

  • 딕셔너리에서 list(d)를 수행하였을 때 딕셔너리에 존재하는 모든 키들이 삽입 순서대로 반환된다고 되어 있다.

  • 따라서 리스트의 순서를 유지하고 싶으면, 딕셔너리를 이용하여 중복 요소를 제거하는 것이 좋다.

성능 비교


  • 그렇다면 순서를 보장하지 않아도 되는 리스트에서 중복을 제거할 때 어떤 것이 더 좋을까?

  • 이를 알아보기 위해서 성능을 비교해보았다.

pip install pytest-benchmark
  • 우선 성능 비교를 위해서 pytest-benchmark 모듈을 설치한다.
import time
import random

import pytest

nums = list(random.randint(1, 100) for _ in range(100))


@pytest.mark.benchmark(
    group="group-name",
    min_rounds=10000,
    timer=time.time,
    disable_gc=True,
    warmup=True
)
def test_use_dict(benchmark):
    @benchmark
    def func1():
        list(dict.fromkeys(nums))

@pytest.mark.benchmark(
    group="group-name",
    min_rounds=10000,
    timer=time.time,
    disable_gc=True,
    warmup=True
)
def test_use_set(benchmark):
    @benchmark
    def func2():
        list(set(nums))
  • 맨 위에서 랜덤으로 1 ~ 100 사이의 정수 리스트를 만들어 준다.

  • 위의 코드는 SET()과 딕셔너리를 이용하여, 리스트에서 중복된 요소를 제거하는 함수를 벤치마크 한 결과이다.

  • 각각 10,000,000 번씩 돌린 결과의 수치들을 뽑아내었다.

  • 랜덤으로 생성된 리스트의 특성에 따라서 차이가 심할 수 있으므로 평균, 표준 편차, 중앙값이 의미가 있을 것이다.

  • 딕셔너리를 이용하는 것보다 SET을 사용하는 것이 중복된 원소를 훨씬 빠르게 제거할 수 있다는 것을 확인할 수 있다. 다만 리스트의 순서를 유지할 필요가 없는 경우에 사용할 수 있을 것이다.

참고 문헌

>> Home