1. 집합(Set)
집합이란 배열과는 달리 순서를 갖지 않는 콜렉션이다. 이러한 특성으로 인해 집합에는 중복되는 값을 저장할 수 없다.
1-1. 집합 선언
let set1: Set<Int> = []
print(type(of: set1), set1) // Set<Int> []
let set2 = Set<Int>()
print(type(of: set2), set2) // Set<Int> []
let set3: Set = [1, 2, 3, 3] // -> 3은 하나만 남고 나머지는 삭제됨
print(type(of: set3), set3) // Set<Int> [3, 2, 1]
집합은 위와 같은 방법을 사용하여 선언할 수 있다. set3의 방법을 가장 많이 사용하며, set3 집합에 3이 2개 들어가있는걸 볼 수 있는데 집합은 중복되는 값을 가질 수 없으므로 하나는 삭제된다. 또한 요소의 타입이 Int이므로 type-inference(타입 추론)에 의해 컴파일러가 집합의 타입을 추론할 수 있다. 따라서 Set<Int>를 Set로 써도 무방하다.
1-2. count
배열에서의 count와 동일하게 집합의 요소 개수를 반환한다.
let mySet: Set = [1, 2, 3, 4, 5]
print("요소 개수: \(mySet.count)")
1-3. isEmpty
이 역시도 배열과 마찬가지로 집합이 비어있으면 true, 그렇지 않으면 false를 반환한다.
var mySet: Set = [1, 2, 3, 4, 5]
print(mySet.isEmpty) // false
mySet = [] // 빈 집합으로 초기화
print(mySet.isEmpty) // true
1-4. insert( ) - 요소 추가
insert 메서드를 사용하여 집합에 값을 추가할 수 있다. 이때 이미 존재하는 값을 추가하려 하면 아무런 변화도 일어나지 않는다.
var mySet: Set = [1, 2, 3, 4, 5]
mySet.insert(5) // 이미 존재하는 값
print(mySet) // [1, 2, 3, 4, 5] **정렬은 매번 달라짐**
mySet.insert(10)
print(mySet) // [1, 2, 3, 4, 5, 10] **정렬은 매번 달라짐**
1-5. remove( ) - 요소 삭제
remove 메서드를 사용하여 존재하는 요소를 삭제할 수 있다. 이때 삭제하려는 요소가 집합에 없는 요소일 수도 있으므로 remove 메서드는 Optional 타입의 결과를 반환한다. 값이 존재하면 해당 값을 반환하고 값이 존재하지 않으면 nil을 반환한다.
var mySet: Set = [1, 2, 3, 4, 5]
print(mySet.remove(5)) // Optional(5)
print(mySet) // [1, 2, 3, 4] **정렬은 매번 달라짐**
print(mySet.remove(999)) // nil
print(mySet) // [1, 2, 3, 4] **정렬은 매번 달라짐**
이는 if 조건문으로도 활용된다.
var mySet: Set = [1, 2, 3, 4, 5]
if let removeValue = mySet.remove(5) {
print("\(removeValue) 삭제 완료") // 여기 실행
} else {
print("삭제할 값이 존재하지 않습니다.")
}
if let removeValue = mySet.remove(999) {
print("\(removeValue) 삭제 완료")
} else {
print("삭제할 값이 존재하지 않습니다.") // 여기 실행
}
1-6. for ~ in
for ~ in 반복문을 사용하여 집합의 각 요소에 접근할 수 있다. 이때 집합은 순서를 갖지 않으므로 접근되는 요소의 순서는 매번 달라질 수 있다. 같은 결과를 원한다면 sorted( ) 메서드를 사용하여 집합을 정렬시킨 뒤 출력하는 방법이 있다.
var mySet: Set = [1, 2, 3, 4, 5]
// 매 실행마다 출력 결과가 달라짐
for i in mySet {
print(i, terminator: " ")
}
print()
// 정렬하였으므로 출력 결과가 동일함
for i in mySet.sorted() {
print(i, terminator: " ")
}
1-7. isSuperset(of: )
- A.isSuperset(of: B)
집합 A가 집합 B의 부모 집합이라면 true, 아니라면 false를 반환한다. 즉, 집합 B의 모든 요소가 집합 A에도 존재한다면 집합 A는 집합 B의 부모 집합이다.
var set1: Set = ["A", "B", "C", "D"]
var set2: Set = ["A", "B", "C"]
print(set1.isSuperset(of: set2)) // true
print(set2.isSuperset(of: set1)) // false
1-8. isSubset(of: )
- A.isSubset(of: B)
집합 A가 집합 B의 자식 집합이라면 true, 아니라면 false를 반환한다. 즉, 집합 A의 모든 요소가 집합 B에도 존재한다면 집합 A는 집합 B의 자식 집합이다.
var set1: Set = ["A", "B", "C", "D"]
var set2: Set = ["A", "B", "C"]
print(set1.isSubset(of: set2)) // false
print(set2.isSubset(of: set1)) // true
1-9. isDisjoint(with: )
- A.isDisjoint(with: B)
집합 A와 집합 B의 교집합이 존재하지 않는 경우, 즉 공통되는 요소가 하나도 존재하지 않는 경우 true, 아니라면 false를 반환한다.
var set1: Set = ["A", "B", "C", "D"]
var set2: Set = ["A", "B", "C"]
print(set1.isDisjoint(with: set2)) // false => ["A", "B", "C"]라는 공통 요소가 존재하기 때문
2. 집합 연산
2-1. union( ) - 합집합
union 메서드를 사용하면 두 집합을 하나로 합친 결과를 얻을 수 있다. 이때 두 집합의 타입이 다르면 오류가 발생한다.
var set1: Set = ["A", "B", "C"]
var set2: Set = ["D", "E", "F"]
var set3: Set = [1, 2, 3]
print(set1.union(set2)) // ["A", "B", "C", "D", "E", "F"] **정렬은 매번 달라짐**
//print(set1.union(set3)) // Type of expression is ambiguous without a type annotation
2-2. subtracting( ) - 차집합
- A.subtracting(B)
subtracting 메서드를 사용하면 집합 A에서 집합 B를 제외한 부분을 얻을 수 있다.
var set1: Set = ["A", "B", "C"]
var set2: Set = ["A", "B", "E"]
print(set1.subtracting(set2)) // ["C"]
print(set2.subtracting(set1)) // ["E"]
2-3. intersection( ) - 교집합
intersection 메서드를 사용하면 두 집합의 공통되는 부분을 얻을 수 있다.
var set1: Set = ["A", "B", "C"]
var set2: Set = ["A", "B", "E"]
print(set1.intersection(set2)) // ["A", "B"] **정렬은 매번 달라짐**
2-4. symmetricDifference( ) - 교집합의 여집합
symmectricDifference 메서드를 사용하면 두 집합에서 공통되는 부분(교집합)을 제외한 집합을 얻을 수 있다.
var set1: Set = ["A", "B", "C"]
var set2: Set = ["A", "B", "E"]
print(set1.symmetricDifference(set2)) // ["C", "E"] **정렬은 매번 달라짐**
Python에서 자주 사용했던 집합이 Swift에도 존재하니 참으로 반갑다.
집합은 특정 값을 하나씩만 얻는 경우 등에 자주 사용되니 잘 기억해둬야겠다.
끝!