swift & iOS/swift

[swift] set

whale3 2022. 2. 9. 12:53

아래 사용한 모든 예제의 출처는 https://docs.swift.org/swift-book/LanguageGuide/CollectionTypes.html#ID484

 

Collection Types — The Swift Programming Language (Swift 5.6)

Collection Types Swift provides three primary collection types, known as arrays, sets, and dictionaries, for storing collections of values. Arrays are ordered collections of values. Sets are unordered collections of unique values. Dictionaries are unordere

docs.swift.org

 


 

set은 안에 들어있는 데이터의 순서가 중요하지 않을 때 그리고 중복된 데이터가 없어야 할 때 사용하기 좋은 타입이다. set은 아래처럼 만든다. 

 

var letters = Set<Character>()

 

<> 에 set에다 저장할 데이터 타입을 넣으면 된다. 또는 아래처럼 바로 데이터를 넣어서 만들 수도 있다. 이미 데이터들의 타입이 String인 것을 스위프트가 알기 때문에 <>에 타입을 적지 않아도 괜찮다. 

 

var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]
var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"] // 타입 추론

 

set에 데이터를 추가하려면 .insert 메소드를 사용한다. 이렇게 데이터를 추가하거나 또는 삭제하기 위해서 let이 아닌 var를 사용해야 한다. 

 

letters.insert("a") // ["a"]

 

set에서 데이터를 삭제할때는 .remove 메소드를 사용한다. set의 모든 데이터를 다 삭제하려면 .removeAll 을 사용한다. .remove 메소드로 반환되는 값은 옵셔널 타입이다. 만약 set에 들어 있지 않은 데이터를 삭제하려고 하면 옵셔널 nil이 리턴된다. 

 

var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"]

if let removedSetMember = favoriteGenres.remove("Rock") {
    print(removedSetMember) // "Rock"
}

favoriteGenres.removeAll()
print(favoriteGenres) // []

 

Set에 특정 데이터가 들어있는지 확인할 때는 .contains 메소드를 사용한다. 

 

print(favoriteGenres.contains("Classical")) // true

 

for...in 반복문을 사용할 수도 있는데 set은 순서 없이 데이터를 저장하기 때문에 만약 특정 순서가 필요하다면 .sorted 메소드를 사용할 수도 있다. 

 

for genre in favoriteGenres {
    print(genre)
}

for genre in favoriteGenres.sorted() {
    print(genre)
}

 

두 개의 set을 가지고 특정 연산을 할 수도 있다. 두 set을 합치거나(합집합), 공통으로 가진 데이터를 찾아내거나(교집합)...

 

출처: https://docs.swift.org/swift-book/LanguageGuide/CollectionTypes.html#ID490

 

intersection: 두 set 모두 가지고 있는 데이터로 새로운 set을 만든다.

symmetricDifference: 각 set에만 있는 데이터가 담긴 새로운 set을 만든다.

union: 두 set의 모든 데이터가 담긴 새로운 set을 만든다

subtracting: parameter로 들어온 set에 없는 데이터가 담긴 새로운 set을 만든다.

 

let oddDigits: Set = [1, 3, 5, 7, 9]
let evenDigits: Set = [0, 2, 4, 6, 8]
let singleDigitPrimeNumbers: Set = [2, 3, 5, 7]

print(oddDigits.intersection(singleDigitPrimeNumbers)) 
// [5, 7, 3]

print(oddDigits.symmetricDifference(evenDigits))
// [8, 1, 9, 7, 0, 4, 2, 3, 6, 5]

print(evenDigits.union(singleDigitPrimeNumbers))
// [8, 7, 0, 4, 2, 6, 3, 5]

print(oddDigits.subtracting(singleDigitPrimeNumbers))
// [9, 1]

 

또한 set을 서로 비교하는 메소드도 있다. == 로 두 set의 데이터가 모두 같은지 비교할 수 있고 isSubset으로 한 set이 다른 set의 subet인지 (속하는지) 또는 isSuperset으로 한 set이 다른 set을 포함하는지 확인할 수 있다. 겹치는 데이터가 없는지는 isDisjoin로 확인할 수 있다. 다만 isSubset의 경우 두 set이 같아도 isSubset은 true를 리턴하기 때문에 두 set의 데이터가 모두 같지 않고, 한 set이 다른 set을 포함하는지 확인하려면 isStrictSubset을 사용하면 된다. 

 

let cities = ["seoul", "london", "paris"]
let favCities = ["seoul", "london", "paris"]
let capitalOfKorea: Set = ["seoul"]
let capitalOfEgypt: Set = ["Cairo"]

print(cities == favCities) // true
print(capitalOfKorea.isSubset(of: cities)) // true
print(cities.isSuperset(of: capitalOfKorea)) // true
print(cities.isDisjoint(with: capitalOfEgypt)) // true


let famousCities: Set = ["seoul", "london", "paris"]

print(cities.isSubset(of: famousCities)) // true
print(cities.isStrictSubset(of: famousCities)) // false

 

참고로 위에 적은 intersection이나 isSubset 같은 연산들은 set과 set 사이에서도 쓰지만 set과 배열, set과 다른 시퀀스 타입에도 사용할 수 있다. 

 

 

또한 set에 reduce나 map 같은 메소드도 사용할 수 있다. 

출처: https://developer.apple.com/documentation/swift/set

var primes: Set = [2, 3, 5, 7]

let sumPrimes = primes.reduce(0, { partialResult, n in partialResult + n })
// let sumPrimes = primes.reduce(0, +)
print(sumPrimes) // 17

let primeStr = primes.map(String.init)
print(primeStr) // ["5", "7", "2", "3"]

 

하지만 위의 reduce나 map의 결과는 배열이기 때문에 이걸 다시 set으로 하려면 아래처럼 해야한다. 

 

let primeStrSet = Set(primes.map(String.init))

 

반응형