Swift의 Collection은 세 종류가 있음.
Set, Dictionary, Array.
Set은 unique한 값들의 unordered collection.
Dictionary는 key-value 관계를 가진 값들의 unordered collection
Array는 값들의 ordered collection
Array는 인덱스가 있으므로 ordered라고 할 수 있고, Set은 중복된 값이 없으므로 unique values, Dictionary는 두 개 값을 key-value의 관계로 묶어둔 것임.
이렇게 보면 이해하기 쉬울듯.
이 친구들은 자신들이 저장할 수 있는 값의 타입과 키에 대해 엄격하기 때문에, 다른 타입이 실수로 collection에 들어갈 수 없다.
//기본형
let arr1: Array[Int] = [1,2,3]
//축약형(더 많이 사용)
let arr2: [Int] = [4,5,6]
var threeDoubles = Array(repeating: 0.0, count: 3)
//threeDoubles 배열은 double 타입을 가지고, [0.0, 0.0, 0.0]의 배열임.
var threeDoubles = Array(repeating: 0.0, count: 3)
var fourDoubles = Array(repeating: 3.3, count: 4)
var newArray = threeDoubles + fourDoubles
// newArray = [0.0, 0.0, 0.0, 3.3, 3.3, 3.3, 3.3]
호환되는 타입의 배열끼리 + 를 사용해서 이어붙일 수 있다.
//count로 원소갯수 접근가능
print("The shopping list contains \(shoppingList.count) items.")
// Prints "The shopping list contains 2 items."
//isEmpty로 비어있는 배열인지 확인가능
if shoppingList.isEmpty {
print("The shopping list is empty.")
} else {
print("The shopping list isn't empty.")
}
// Prints "The shopping list isn't empty."
//append로 배열의 마지막 원소에 붙이기 가능
shoppingList.append("Flour")
// shoppingList now contains 3 items, and someone is making pancakes
//+=로도 append 수행가능
shoppingList += ["Baking Powder"]
// shoppingList now contains 4 items
//+=로 여러개 붙일수도 있음
shoppingList += ["Chocolate Spread", "Cheese", "Butter"]
// shoppingList now contains 7 items
//인덱스로 원소 확인 가능
var firstItem = shoppingList[0]
// firstItem is equal to "Eggs"
//인덱스로 원소 바꾸기 가능
shoppingList[0] = "Six eggs"
// the first item in the list is now equal to "Six eggs" rather than "Eggs"
//4...6처럼 범위 설정해서 인덱스 접근 가능
shoppingList[4...6] = ["Bananas", "Apples"]
// shoppingList now contains 6 items
//insert로 원하는 인덱스에 원소 집어넣기 가능
shoppingList.insert("Maple Syrup", at: 0)
// shoppingList now contains 7 items
// "Maple Syrup" is now the first item in the list
//remove로 원하는 인덱스 원소 삭제 가능
let mapleSyrup = shoppingList.remove(at: 0)
// the item that was at index 0 has just been removed
// shoppingList now contains 6 items, and no Maple Syrup
// the mapleSyrup constant is now equal to the removed "Maple Syrup" string
이 외에도 removeAll(), removeLast(), removeFirst(), removeSubrange() 등 여러 메소드들이 있음.
너무 많아서 차차 알아가보도록 하자.
Array의 원소를 하나씩 보고 싶을 때는 for...in을 사용하면 된다.
var arr1 = [1,2,3,4,5]
for item in arr1{
print(item)
}
이걸 인덱스와 함께 보고 싶다면 enumerated() 메소드를 사용하면 된다.
var arr1 = [1,2,3,4,5]
for (index, item) in arr1.enumerated(){
print("Item \(index+1): \(item)")
}
//Item1: 1
//Item2: 2
//Item3: 3
//Item4: 4
//Item5: 5
item의 순서가 중요하지 않고, 중복되지 않은 단 하나의 item을 가지는 것이 중요하다면 Array 대신 Set을 쓰면 된다.
Set에 저장되려면 타입이 Hashable 해야 한다.
그 말인즉슨, 타입이 자신의 값을 hash value로 만들 수 있는 방법을 제공해야 한다는 것이다.
hash value는 Int값으로, 같다고 비교되는 모든 객체에 대해 같은 값을 가진다.
예를 들어 a==b라면, a와 b의 해시값은 같다고 할 수 있다.
스위프트의 모든 기본 타입은 Hashable하며, Set value나 Dictionary key에 쓰일 수 있다.
직접 만든 타입의 경우 Hashable 프로토콜을 따르도록 만들어주면 Set이나 Dictionary에 사용 가능하다.
Set<Element>
의 기본형을 가지며, 함축형은 없음.
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."
var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]
// favoriteGenres has been initialized with three initial items
Set이라고 명시를 하지 않으면 선언한 것을 Array와 구분할 수가 없으므로, Set 선언 시에는 타입을 적어줘야 한다. 다만 타입 추론을 통해 < Element >는 적지 않아도 된다.
이런 식으로 쓰면 됨.
var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"]
//Array와 거의 비슷한듯?
//원소의 갯수를 알수있는 count
print("I have \(favoriteGenres.count) favorite music genres.")
// Prints "I have 3 favorite music genres."
//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."
//Set에 새로운 원소 삽입. insert 사용
favoriteGenres.insert("Jazz")
// favoriteGenres now contains 4 items
//Set에서 원소 삭제하기. remove 사용 Set이 해당 원소를 포함하지 않는다면 nil 반환
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."
//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."
Array와 마찬가지로 for...in 을 사용해서 훑어볼 수 있다.
for genre in favoriteGenres {
print("\(genre)")
}
// Classical
// Jazz
// Hip hop
Set은 unordered이므로 index에 따라 순회할 수는 없지만, sorted() 메소드를 사용하면 < 을 사용해 정렬할 수 있다.
for genre in favoriteGenres.sorted() {
print("\(genre)")
}
// Classical
// Hip hop
// Jazz
두 개의 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]
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]
a는 b의 superset, b는 a의 subset, b와 c는 disjoint
let houseAnimals: Set = ["🐶", "🐱"]
let farmAnimals: Set = ["🐮", "🐔", "🐑", "🐶", "🐱"]
let cityAnimals: Set = ["🐦", "🐭"]
houseAnimals.isSubset(of: farmAnimals)
// true
farmAnimals.isSuperset(of: houseAnimals)
// true
farmAnimals.isDisjoint(with: cityAnimals)
// true
딕셔너리는 같은 타입의 키들과 같은 타입의 값(value)들의 association이다.
순서가 없는 것도 특징!
key들은 unique한데, 이것들이 값들의 식별자가 돼 줌.
진짜 사전처럼 특정 단어의 정의를 찾아보는 느낌.
//기본형
let dict1: Dictionary<Int:String> = [4:"four", 1:"one"]
//축약형
let dict2: [Int:String] = [4:"four", 1:"one"]
var airports = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
//딕셔너리의 pair 갯수 count로 접근
print("The airports dictionary contains \(airports.count) items.")
// Prints "The airports dictionary contains 2 items."
//isEmpty 사용가능
if airports.isEmpty {
print("The airports dictionary is empty.")
} else {
print("The airports dictionary isn't empty.")
}
// Prints "The airports dictionary isn't empty."
//이런식으로 추가 가능, LHR이 key, London이 value
airports["LHR"] = "London"
// the airports dictionary now contains 3 items
//key LHR의 value 수정가능
airports["LHR"] = "London Heathrow"
// the value for "LHR" has been changed to "London Heathrow"
updateValue(_: forKey:) 메소드는 해당 키의 값을 바꾸고, 이전 값을 반환해준다. 키가 없다면 새로 생성해서 만듦.
if let oldValue = airports.updateValue("Dublin Airport", forKey: "DUB") {
print("The old value for DUB was \(oldValue).")
}
// Prints "The old value for DUB was Dublin."
키와 값 삭제는 다음과 같다.
airports["APL"] = "Apple International"
// "Apple International" isn't the real airport for APL, so delete it
airports["APL"] = nil
// APL has now been removed from the dictionary
removeValue(forKey:) 메소드는 해당 키를 삭제하고, 이전값을 반환해준다. 키가 없다면 nil을 반환한다.
if let removedValue = airports.removeValue(forKey: "DUB") {
print("The removed airport's name is \(removedValue).")
} else {
print("The airports dictionary doesn't contain a value for DUB.")
}
// Prints "The removed airport's name is Dublin Airport."
마찬가지로 for...in 을 사용하고, (key, value)의 튜플 형태로 값이 반환된다.
for (airportCode, airportName) in airports {
print("\(airportCode): \(airportName)")
}
// LHR: London Heathrow
// YYZ: Toronto Pearson
//key와 value에도 따로 접근할 수 있다.
for airportCode in airports.keys {
print("Airport code: \(airportCode)")
}
// Airport code: LHR
// Airport code: YYZ
for airportName in airports.values {
print("Airport name: \(airportName)")
}
// Airport name: London Heathrow
// Airport name: Toronto Pearson
//이런 식으로 키나 값을 Array형태로 만들 수도 있다.
let airportCodes = [String](airports.keys)
// airportCodes is ["LHR", "YYZ"]
let airportNames = [String](airports.values)
// airportNames is ["London Heathrow", "Toronto Pearson"]
Set와 마찬가지로 unordered이므로 어떤 정렬형태를 갖고 싶다면 key나 value에 sorted() 메소드를 사용하면 된다.