세트 SET
스위프트에서 컬렉션 타입인 세트(set
)를 살펴보겠습니다.
세트는 말 그대로 공통적인 것들을 묶어놓은 것이라고 볼 수 있습니다. 배열과 반대로 순서가 중요하지 않고, 유일한 값들로 채우려고 할 때 세트가 유용합니다. 또, 세트는 집합으로 활용하기에 아주 좋은 타입입니다
세트는 Set 키워드와 타입 이름의 조합으로 써줍니다. 또, 배열과 마찬가지로 대괄호로 값들을 묶어 세트 타입임을 표현합니다. 배열과 달리 줄여서 표현할 수 있는 축약형 ( Array<Int>를 [int]로 축약할 수 있었던) 이 없습니다. let
키워드를 사용하여 상수로 선언하면 변경 불가능한 세트, var
키워드를 사용하여 변수로 선언해 주성 할 수 있습니다. 마찬가지로 isEmpty
프로퍼티를 통해 비어있는 세트 인지 확인할 수 있겠죠. 그리고 count
프로퍼티로 세트의 요소 개수를 확인할 수 있습니다.
세트(Set
)는 두 가지 차이점이 있다는 점을 제외하면 배열(array
)과 같은 값의 모음입니다.
- 항목은 어떤 순서로도 저장되지 않습니다. 사실상 임의의 순서로 저장됩니다.
- 한 세트에 항목이 두 번 나타날 수 없습니다. 즉, 중복이 안됩니다. 모든 항목은 고유해야 합니다.
다음과 같이 배열에서 직접 집합을 만들 수 있습니다.
let colors = Set(["red", "green", "blue"])
//print = blue, green, red
출력된 값을 보면 우리가 생성 한 순서와 일치하지 않는다는 것을 알 수 있습니다. 실제로 임의의 순서가 아니라 순서가 지정되지 않았을 뿐입니다. Swift는 순서대로 표시하지 않습니다. 순서가 지정되지 않았기 때문에 배열에서와 같이 숫자 위치를 사용하여 집합에서 값을 읽을 수 없습니다.
세트에 중복 항목을 삽입하려고 하면 중복 항목이 무시됩니다.
let colors2 = Set(["red", "green", "blue", "red", "blue"])
//print = green, red, blue
세트의 기본 프로퍼티
let emptyIntSet:Set = []
print(emptyIntSet)
let emptyIntSet:Set = Set()
print(emptyIntSet)
var animal: Set<String> = ["dog", "cat", "monkey", "lion", "dog"]
// String 타입의 Set을 선언과 동시에 초기화를 합니다.
print(animal.isEmpty)
// animal이 비어있는지 여부를 확인합니다.
animal.insert("tiger")
// animal에 값을 한 개 추가합니다.
print(animal.count)
// Set animal이 가진 값의 수를 세지만, 중복되는 것은 제외합니다.
print(animal.remove("cat")
// 요소가 삭제되면 해당 값을, 삭제되지 않으면 nil을 반환합니다.
세트 역시 기본적으로 요소를 추가하거나, 삭제를 할 수 있도록 프로퍼티를 제공하고 있고, 또 그것들이 정상적으로 수행되었는지 판단할 수 있도록 하고 있습니다.
var someStrSet:Set = ["ab", "bc", "cd", "de"]
if let someVal = someStrSet.remove("cd") {
print(someVal)
print(someStrSet)
} else {
print("cannot find element to remove")
}
//print
cd
["de", "ab", "bc"]
세트와 배열이 다른 이유는??
세트와 배열은 모두 Swift에서 중요하며, 그 차이점이 무엇인지 이해하면 주어진 상황에서 어떤 것을 선택할지 이해하는 데 도움이 됩니다. 세트와 배열은 모두 데이터 모음이므로 단일 변수 내에 여러 값을 보유합니다. 그러나 값을 유지하는 방법 이 중요합니다. 세트는 순서가 지정되지 않고 중복을 포함할 수 없는 반면 배열은 순서를 유지하고 중복 을 포함 할 수 있습니다.
이 두 가지 차이점은 작게 보일 수 있지만 부작용이 있습니다. 세트는 추가 한 순서대로 개체를 저장할 필요가 없기 때문에 대신 빠른 검색을 위해 최적화하는 임의의 순서로 개체를 저장할 수 있습니다. 따라서 "이 세트에 항목 X가 포함되어 있습니까?"라고 말하면 세트의 크기에 관계없이 순식간에 답변을 얻을 수 있습니다.
이에 비해 배열은 항목을 제공 한 순서대로 저장해야 합니다. 따라서 항목 X가 10,000개의 항목을 포함하는 배열에 존재하는지 확인하려면 Swift가 첫 번째 항목에서 시작하여 발견될 때까지 모든 단일 항목을 확인해야 합니다.
즉, 큰 차이점은 "이 항목이 있습니까?"라고 말하고 싶을 때 세트가 더 유용하다는 것을 의미합니다. 예를 들어, 단어가 사전에 나타나는지 확인하려면 세트를 사용해야 합니다. 중복이 없고 빠른 검색을 할 수 있습니다.
예시
var readings = Set([true, false, true, true])
var ratings = Set([1, 1, 1, 2, 2, 2])
//세트에는 고유한 항목이 포함되어 있어야 하므로 중복된 값들은 삭제됩니다.
let someStrSet:Set = ["ab","bc","cd","de","ab"]
print(someStrSet) //bc, ab, de, cd
잘못된 예시
let earthquakeStrengths = Set(1, 1, 2, 2)
let staffReviews = Set([1, 2, 1, 2, 3])
세트의 선언 와 생성
// 빈 세트를 생성하는 방법
var names1: Set<String> = Set<String>()
var names2: Set<String> = []
// Array와 마찬가지로 대괄호를 사용한다.
var names3: Set<String> = ["서근", "미진", "철수", "포뇨", "소피아"]
// 타입 추론을 사용하면 컴파일러가 Set가 아닌 Array로 타입을 지정함
var numbers = [100, 200, 300]
print(type(of: numbers)) // Array<Int>
print(names1.isEmpty) // true
print(names3.isEmpty) // false
print(names3.count) // 5
만약 타입 추론을 사용하면 컴파일러가 Set
가 아닌 Array
로 타입을 지정해주기 때문에 만약 Set를 사용하려면 반드시 Set
타입을 지정해줘야 합니다.
또, 세트에 요소를 추가하고 싶다면 Insert(_:)
메서드를 사용합니다. 요소를 삭제하고 싶다면 remove(_:)
메서드를 사용하는데, 메서드를 사용하면 해당 요소가 삭제된 후 반환됩니다.
var names3: Set<String> = ["서근", "미진", "철수", "포뇨", "소피아"]
names3.insert("캘시퍼")
print(names3) // ["소피아", "철수", "서근", "캘시퍼", "미진", "포뇨"]
names3.remove("미진")
names3.remove("소피아")
print(names3) // ["캘시퍼", "철수", "서근", "포뇨"]
print(names3.remove("민지")) // nil
세트의 활용 - 집합 연산
세트는 자신 내부의 값들이 모두 유일함을 보장하므로, 집합 관계를 표현하고자 할 때 유용하게 쓰일 수 있으며, 두 세트의 교집합, 합집합 등을 연산하기에 매우 용이합니다. 또한 sorted()
메서드를 통해 정렬된 배열을 반환해줄 수도 있습니다.
- intersection - 교집합
- symmetricDifference - 여집합
- union - 합집합
- subtracting - 차집합
let myFavoriteFruits: Set<String> = ["사과", "배", "포도", "메론", "수박"]
let yourFavoriteFruits: Set<String> = ["메론", "수박", "딸기", "참외", "자두"]
// 교집합
let intersectSet: Set<String> = myFavoriteFruits.intersection(yourFavoriteFruits)
print(intersectSet)
// ["메론", "수박"]
// 여집합
let symmetricDiffSet: Set<String> = myFavoriteFruits.symmetricDifference(yourFavoriteFruits)
print(symmetricDiffSet)
// ["사과", "배", "포도", "참외", "자두", "딸기"]
// 합집합
let unionSet: Set<String> = myFavoriteFruits.union(yourFavoriteFruits)
print(unionSet)
// ["자두", "메론", "사과", "포도", "참외", "수박", "배", "딸기"]
// 차집합
let subtracSet: Set<String> = myFavoriteFruits.subtracting(yourFavoriteFruits)
print(subtracSet)
// ["사과", "배", "포도"]
//정렬된 배열을 반환해줌
print(unionSet.sorted())
// ["딸기", "메론", "배", "사과", "수박", "자두", "참외", "포도"]
세트의 활용 - 포함관계 연산
세트는 포함 관계를 연산할 수 있는 메서드로 구현되어 있습니다.
let 광역시: Set<String> = ["대전", "대구", "부산", "인천", "울산", "광주"]
let 도: Set<String> = ["경기도", "강원도", "충북", "충남", "전북", "전남", "경북", "경남"]
let 한국: Set<String> = 광역시.union(도)
print(한국)
/*
["전남", "경기도", "대구", "충남", "충북",
"부산", "경북", "대전", "전북", "광주", "울산", "경남", "인천", "강원도"]
*/
print(광역시.isDisjoint(with: 도)) // 서로 베타적인가? true
print(광역시.isSubset(of: 한국)) // 광역시가 한국의 부분집합인가? true
print(한국.isSuperset(of: 광역시)) // 한국이 광역시의 전체집합인가? true
print(한국.isSuperset(of: 도)) // 한국이 도의 전체집합인가? true
Set TEST : 문제를 풀려면 이곳을 클릭해주세요.
읽어주셔서 감사합니다🤟
'SWIFT > Grammar' 카테고리의 다른 글
Swift : 기초문법 [Array vs Set vs Tuple] 간단 비교 (0) | 2021.02.19 |
---|---|
Swift : 기초문법 [튜플 - TUPLES] 배열과의 차이점 (1) | 2021.02.18 |
Swift : 기초문법 [배열(Array)] (0) | 2021.02.18 |
Swift : 기초문법 [어노테이션(annotations) 타입] (0) | 2021.02.18 |
Swift : 기초문법 [ 변수와 상수] (1) | 2021.02.18 |