MapSet — 중복을 허용하지 않는 집합
MapSet — 중복을 허용하지 않는 집합
집합(set)은 어떤 종류의 요소든 중복 없이 담을 수 있는 데이터 구조예요. 순서도 따지지 않죠. Elixir에서 집합을 쓸 때 가장 먼저 떠올리는 구조가 바로 MapSet이에요.
출처: MapSet
본문
집합은 MapSet.new/0으로 만들 수 있어요:
iex> MapSet.new()
MapSet.new([])
집합의 요소는 모두 같은 타입일 필요 없어요. 열거 가능한(Enumerable) 값에서 MapSet.new/1로 채워 넣을 수도 있죠:
iex> MapSet.new([1, :two, {"three"}])
MapSet.new([1, :two, {"three"}])
요소는 MapSet.put/2로 넣을 수 있어요:
iex> MapSet.new([2]) |> MapSet.put(4) |> MapSet.put(0)
MapSet.new([0, 2, 4])
정의상 집합은 중복 요소를 담을 수 없어요. 이미 들어 있는 요소를 다시 넣으면 아무 일도 일어나지 않아요(no-op). 이 특성이 집합을 "멤버십 검사"에 특히 유용하게 만들어 주죠:
iex> map_set = MapSet.new()
iex> MapSet.put(map_set, "foo")
MapSet.new(["foo"])
iex> map_set |> MapSet.put("foo") |> MapSet.put("foo")
MapSet.new(["foo"])
MapSet은 내부적으로 %MapSet{} 구조체(struct)로 표현돼요. "이 값이 정말 MapSet인가"를 패턴 매칭으로 확인하고 싶을 때 이 구조체를 쓰면 돼요:
iex> match?(%MapSet{}, MapSet.new())
true
단, 이 구조체의 필드는 전부 비공개(private) 예요. 필드에 직접 접근하면 안 되고, 집합을 다룰 땐 이 모듈이 제공하는 함수들을 써야 해요. 필드 구조는 내부 구현일 뿐이니까요.
MapSet은 다른 컬렉션형 데이터 구조에서부터 만들 수도 있어요. 예를 들어 MapSet.new/1이나 Enum.into/2를 쓰면 리스트나 Map 같은 걸 집합으로 바꿀 수 있죠.
MapSet은 Erlang의 :sets(버전 2) 위에 만들어져요. 그래서 두 구조는 로그 시간 복잡도 같은 여러 성질을 함께 가져요. Erlang :sets(버전 2)는 다시 Map 위에 구현되어 있으니, 실행 시간 복잡도에 대해 더 알고 싶다면 Map 문서를 함께 보면 좋아요.
더 알아보기
MapSet.new/1,MapSet.put/2,MapSet.member?/2— 집합 만들기와 멤버십 검사MapSet.union/2,MapSet.intersection/2,MapSet.difference/2— 집합 연산- Enum.into/2 — 다른 컬렉션을 집합으로 변환
- Map — 집합의 내부 기반이 되는 키-값 구조