Set의 개념

Dart에서 Set은 중복되지 않는 고유한 값들의 모음을 의미한다. 수학적인 집합과 유사하게, Set 내의 원소는 고유하며 중복을 허용하지 않는다. Dart의 Set은 리스트와 같은 컬렉션이지만, 주요 차이점은 중복된 요소를 허용하지 않는다는 점이다. 이는 특정한 요소가 이미 존재하는지 여부를 검사하거나, 중복을 제거할 때 유용하다.

Set의 생성과 기본 사용법

Set은 Dart에서 리스트와 유사하게 사용할 수 있으며, 다음과 같은 방법으로 생성할 수 있다:

Set<int> numbers = {1, 2, 3, 4, 5};
Set<String> names = {'Alice', 'Bob', 'Charlie'};

혹은 빈 Set을 생성한 후에 값을 추가할 수 있다:

Set<int> emptySet = {};
emptySet.add(10);

Set은 여러 타입의 값들을 저장할 수 있으며, Dart의 타입 시스템을 이용하여 제네릭 형태로 사용할 수 있다.

Set의 주요 연산

수학에서와 마찬가지로, Dart의 Set에서도 다양한 연산을 수행할 수 있다. 대표적인 연산으로는 합집합, 교집합, 차집합이 있으며, 이들 연산은 모두 Set에서 제공하는 메서드를 통해 수행할 수 있다.

합집합 (Union)

두 집합 AB의 합집합은 다음과 같이 정의된다:

A \cup B = \{ x \mid x \in A \text{ 또는 } x \in B \}

Dart에서 합집합은 union 메서드를 사용하여 구할 수 있다:

Set<int> a = {1, 2, 3};
Set<int> b = {3, 4, 5};

Set<int> unionSet = a.union(b);
print(unionSet); // {1, 2, 3, 4, 5}

교집합 (Intersection)

두 집합 AB의 교집합은 다음과 같이 정의된다:

A \cap B = \{ x \mid x \in A \text{ 그리고 } x \in B \}

교집합은 intersection 메서드를 사용하여 구할 수 있다:

Set<int> a = {1, 2, 3};
Set<int> b = {3, 4, 5};

Set<int> intersectionSet = a.intersection(b);
print(intersectionSet); // {3}

차집합 (Difference)

차집합은 두 집합 AB에서 A에만 존재하고 B에는 존재하지 않는 원소들로 구성된다:

A - B = \{ x \mid x \in A \text{ 그리고 } x \notin B \}

Dart에서 차집합은 difference 메서드를 통해 구할 수 있다:

Set<int> a = {1, 2, 3};
Set<int> b = {3, 4, 5};

Set<int> differenceSet = a.difference(b);
print(differenceSet); // {1, 2}

원소 포함 여부 확인 (Membership)

집합에서 특정 원소가 포함되어 있는지 확인하는 연산은 매우 중요하다. Dart에서는 contains 메서드를 사용하여 특정 값이 집합에 포함되어 있는지 여부를 검사할 수 있다:

Set<int> numbers = {1, 2, 3, 4, 5};
print(numbers.contains(3)); // true
print(numbers.contains(6)); // false

Set의 반복 처리

Set은 Dart의 for 루프나 forEach 메서드를 통해 반복 처리할 수 있다. 이는 리스트와 유사하게 동작하지만, Set의 경우 순서가 보장되지 않는다.

Set<String> names = {'Alice', 'Bob', 'Charlie'};
for (var name in names) {
  print(name);
}

혹은 forEach를 사용하여 다음과 같이 처리할 수 있다:

names.forEach((name) {
  print(name);
});

Set의 변환 및 정렬

Set은 순서가 없는 컬렉션이므로, 정렬된 순서로 데이터를 처리하고자 할 때는 리스트로 변환한 후에 정렬할 수 있다. Dart에서는 toList 메서드를 사용하여 Set을 리스트로 변환할 수 있다:

Set<int> numbers = {5, 3, 1, 4, 2};
List<int> sortedList = numbers.toList()..sort();
print(sortedList); // [1, 2, 3, 4, 5]

Set과 중복 처리

Set은 중복된 원소를 허용하지 않는다. Dart에서 중복된 원소를 추가하려고 하면 자동으로 무시된다. 예를 들어, 동일한 값을 여러 번 추가해도 결과는 동일하다:

Set<int> numbers = {1, 2, 3};
numbers.add(3);
print(numbers); // {1, 2, 3}

이 특성 덕분에 Set은 중복을 제거해야 하는 상황에서 유용하다. 예를 들어, 리스트에 중복된 값이 있을 경우 이를 Set으로 변환하면 중복된 값이 자동으로 제거된다:

List<int> numberList = [1, 2, 2, 3, 4, 4, 5];
Set<int> uniqueNumbers = numberList.toSet();
print(uniqueNumbers); // {1, 2, 3, 4, 5}

Set의 크기와 비어 있는지 확인

Dart의 Set에서는 집합의 크기를 확인하기 위해 length 속성을 사용하고, 비어 있는지 확인하려면 isEmptyisNotEmpty 메서드를 사용할 수 있다:

Set<String> names = {'Alice', 'Bob', 'Charlie'};
print(names.length); // 3
print(names.isEmpty); // false
print(names.isNotEmpty); // true

이처럼 Set은 크기와 상태를 쉽게 파악할 수 있는 메서드를 제공하여 데이터를 효율적으로 관리할 수 있다.

Set의 추가 및 제거

Set은 리스트처럼 데이터를 동적으로 추가하거나 제거할 수 있다. Dart에서는 addremove 메서드를 사용하여 값을 추가하거나 삭제할 수 있다. 여러 개의 값을 한 번에 추가하거나 삭제하려면 addAllremoveAll을 사용할 수 있다.

Set<int> numbers = {1, 2, 3};
numbers.add(4); // 4 추가
numbers.remove(2); // 2 제거
print(numbers); // {1, 3, 4}

여러 값을 추가하고 제거할 때는 다음과 같이 한다:

Set<int> numbers = {1, 2, 3};
numbers.addAll([4, 5, 6]); // 여러 값을 추가
numbers.removeAll([1, 2]); // 여러 값을 제거
print(numbers); // {3, 4, 5, 6}

Set의 복사

Set을 복사하려면 Set.from 생성자를 사용하거나, toSet 메서드를 통해 새로운 Set을 생성할 수 있다. 이는 원본 Set과 동일한 값을 가지는 새로운 Set을 만들지만, 서로 다른 객체로 관리된다.

Set<int> numbers = {1, 2, 3};
Set<int> copiedSet = Set.from(numbers);
print(copiedSet); // {1, 2, 3}

이처럼 Dart에서의 Set은 다양한 연산과 메서드를 통해 쉽게 데이터를 관리하고 조작할 수 있는 유용한 도구이다.