Apple 제공 Swift 프로그래밍 가이드(3.0.1)의 Collection Types 중 Set 부분을 공부하며 정리한 글입니다. 개인적인 생각도 조금 들어가있습니다.
들어가며
Set은 같은 타입의 값을, 중복되지 않게, 순서없이 저장하는 Collection Type.
저장순서를 알 필요없고, Collection 안의 값이 모두 유니크해야 할 때 Set을 사용하면 적절하다.
<note> Swift’s Set type is bridged to Foundation’s NSSet class.
Hash Values for Set Types
Set에 저장될 Type은 반드시 hashable 해야한다.
hashable 한 Type이란? : 그 Type이 hash value를 알려줄 수 있다
hash value 란? : a = b 일때 a.hashValue == b.hashValue 를 만족하는 Int value
Swift의 모든 기본 타입(String, Int, Double, Bool 등)은 default로 hashable 하다. 또한 Enumeration case value 역시 default로 hashable 하다. 즉 이런 타입들은 Set에 저장될 수 있고 Dictionary의 key 값이 될 수도 있다. Int나 Bool 타입이 Dictionary Key로 쓰일 수 있다는 점이 Objective-C와 비교가 된다.
자신이 만든 Custom Type을 Set에 저장하거나 Dictionary의 Key 타입으로 사용하고 싶다면 Hashable protocol 을 따르도록 구현해야 한다. 참고로 Hashable protocol은 Equatable protocol을 따르고 있으므로 == operator 구현도 해야한다.
Hashable protocol을 따르기 위해서는
hashValue 라는 프로퍼티의 getter 제공
== (equals operator) 구현 제공. 다음 조건을 만족할 수 있도록
a == a (Reflexivity)
a == b 는, 즉 b == a (Symmetry)
a == b && b == c 는, 즉 a == c (Transitivity)
Set Type Syntax
Set<Element>으로 만든다. Element는 Set에 저장할 값의 타입이다.
참고로 Set은 Array와 다르게 shorthand form이 없다. (var intArray: [Int] 는 Int 타입을 저장하는 Array를 만들어주지만, 이와 비슷하게 var intSet: <Int> 를 시도해보면 컴파일 에러)
Creating and Initializing an Set
// 1. Empty Set 생성
var letters = Set<character>()
print("letters is of type Set<character> with \(letters.count) items.")
// prints "letters is of type Set<character> with 0 items.”
letters.insert("a")
// letters now contains 1 value of type Character
letters = []
// letters is now an empty set, but is still of type Set<Character>
// 2.Array Literal 을 이용하여 Set 생성
var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]
// favoriteGenres has been initialized with three initial items
// var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"] 만 써도 String타입이 저장될 Set을 유추해준다.
// <주의> Set을 명시하지 않으면 favoriteGenres는 array가 된다.
Accessing and Modifying a Set
// 1. Set 안에 몇 개의 Item이 있는지 체크하기 위해 -> count 프로퍼티
print("I have \(favoriteGenres.count) favorite music genres.")
// prints "I have 3 favorite music genres.”
// 2. Set 안이 비어있는지 체크하기 위해 -> isEmpty 프로퍼티
if favoriteGenres.isEmpty {
print("As far as music goes, I'm not picky.")
}
else {
print("I have particular music preferences.")
}
// prints "I have particular music preferences.”
// 3. Set 에 Item 추가를 위해 -> insert 메서드
favoriteGenres.insert("Jazz")
// favoriteGenres now contains 4 items
// 4. Set의 Item 제거를 위해 -> remove 메서드
// remove(Item) 메서드는 Item이 Set에 있었다면 지우고 그 Item을 반환하고
// Item이 Set에 없었다면 nil을 반환한다
// removeAll() 메서드도 있음
if let removedGenre = favoriteGenres.remove("Rock") {
print("\(removedGenre)? I'm over it.")
}
else {
print("I never much cared for that.")
}
// prints "Rock? I'm over it.”
// 5. 특정 Item이 Set 안에 들어있는지 체크하기 위해 -> contains 메서드
if favoriteGenres.contains("Funk") {
print("I get up on the good foot.")
}
else {
print("It's too funky in here.")
}
// prints "It's too funky in here.”
Iterating Over a Set
for genre in favoriteGenres {
print("\(genre)")
}
// Classical
// Jazz
// Hip hop
// Set 안의 Item을 특정 순서로 순회하고 싶다면 sorted() 메서드를 사용
// Item을 < 연산자로 sorting 한 array가 반환됨
for genre in favoriteGenres.sorted() {
print("\(genre)")
}
// Classical
// Hip hop
// Jazz
Performing Set Operations
<Fundamental Set Operations>
기본적인 Set operation 들을 효율적으로 수행하는 방법을 어떻게 제공하는지 알아보자.
a와 b는 각각 Set이다. 각 벤다이어그램 위에 표기된 메서드는 벤다이어그램의 초록색 부분에 해당하는 Item들로 구성된 새로운 Set을 생성하여 반환해준다. 자세한 설명은 생략한다.
let oddDigits: Set = [1, 3, 5, 7, 9]
let evenDigits: Set = [0, 2, 4, 6, 8]
let singleDigitPrimeNumbers: Set = [2, 3, 5, 7]
oddDigits.union(evenDigits).sorted()
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
oddDigits.intersection(evenDigits).sorted()
// []
oddDigits.subtracting(singleDigitPrimeNumbers).sorted()
// [1, 9]
oddDigits.symmetricDifference(singleDigitPrimeNumbers).sorted()
// [1, 2, 9]
<Set Membership and Equality>
a, b, c는 각각 Set이며 a는 b의 superset, b는 a의 subset, b와 c는 서로에게 disjoint한 관계이다.
“is equal” operator (==) : 두 Set의 내용이 전부 동일 (Item의 type, count, value 모두)
isSubset(of:) : subset인지를 판별
isSuperset(of:) : superset인지를 판별
isStrictSubset(of:) : subset이면서, subset!=superset
isStrictSuperset(of:) : superset이면서, subset!=superset
isDisjoint(with:) : 두 Set 간의 교집합이 없음
let houseAnimals: Set = ["🐶", "🐱"]
let farmAnimals: Set = ["🐮", "🐔", "🐑", "🐶", "🐱"]
let cityAnimals: Set = ["🐦", "🐭"]
houseAnimals.isSubset(of: farmAnimals)
// true
farmAnimals.isSuperset(of: houseAnimals)
// true
farmAnimals.isDisjoint(with: cityAnimals)
// true
// 추가설명
let myAnimals: Set = ["🐮", "🐔"]
let myFriendAnimals: Set = ["🐮", "🐔", "🐑", "🐶", "🐱"]
myAnimals.isStrictSubset(of: farmAnimals)
// true
myFriendAnimals.isStrictSubset(of: farmAnimals)
// false
'Swift 공식 가이드 > Swift 3' 카테고리의 다른 글
Control Flow (0) | 2017.02.15 |
---|---|
Collection Types - Dictionary (0) | 2017.02.11 |
Collection Types - Array (0) | 2017.02.11 |
Strings and Characters (2) | 2017.02.05 |
Basic Operators (0) | 2017.02.05 |