Swift Collection Types
Collections - Arrays, Sets, Dictionaries
Swift 는 다음 3가지 primary collection types
를 제공한다.
- Array
- Set
- Dictionary
Collections
는 data type 이 명확히 정의되어 있으므로 실수로 다른 type 의 데이터를 넣을 수 없다.
1. Mutability of Collections (콜렉션의 변경) 👩💻
만약 Collections
를 var(variable)할당한다면, 해당 collections 는 변경할 수 있다(mutable).
하지만 let(constant)에 할당한다면, 해당 collections 는 크기와 내용물 모두 불변이다(immutable).
2. Arrays (배열) 👩💻
Array
는 순서가 지정된 random-access collection 이다.
(RandomAccessCollection protocol 을 따르는, 즉, random-access 를 지원하는 collection 이다).
Swift 의 Array 타입은 Foundation
의 NSArray
클래스와 연결되고, 이를 확장해 Array 에서 NSArray 메서드를 사용할 수 있게 해준다.
따라서, import Foundation
을 하면 Array 를 캐스팅 하지 않고 NSArray 메서드를 사용
할 수 있다.
1. Array Type Syntax
다음 두 가지 형태의 initializer syntax
를 사용할 수 있다.
var someArray = Array<Element>()
var someArray = [Int]() // Array Type Shorthand Syntax (배열의 축약형 문법)
var someArray: [Element] = [] // Array Type Shorthand Syntax (배열의 축약형 문법)
2. Creating an Empty Array
var someArray: [Int] = []
Shorthand Syntax
를 이용해 빈 배열을 생성했다.
someArray.append(5)
someArray.append(9)
print(someArray) // [5, 9]
이제 someArray 는 5
, 9
를 순서대로 저장하고있다.
someArray = []
print(someArray) // []
Empty Array Literal([]
)를 이용해 someArray 를 다시 Empty Array
로 만들더라도 [Int]
타입은 변하지 않는다.
3. Creating an Array with a Default Value
var threeDoubles = Array(repeating: 0.0, count: 3)
print(threeDoubles) // [0.0, 0.0, 0.0]
4. Creating an Array by Adding Two Arrays Together
두 개의 배열을 +
연산자를 이용해 더해 새 배열을 생성할 수 있다.
var threeDoubles = Array(repeating: 0.0, count: 3)
var anotherThreeDoubles = Array(repeating: 2.5, count: 3)
var sixDoubles = threeDoubles + anotherThreeDoubles
print(sixDoubles) // [0.0, 0.0, 0.0, 2.5, 2.5, 2.5]
5. Creating an Array with an Array Literal
var shoppingList: [String] = ["Eggs", "Milk"]
만약 위와 같이 Array Literal
이 한 가지 타입으로 구성되었다면, Swift 는 해당 배열의 타입을 추론한다.
var shoppingList = ["Eggs", "Milk"]
Array
는 2 가지 이상의 타입을 저장 할 수 있다. 하지만 이 경우 Type Inference
는 사용할 수 없다.
반드시 [Any]
타입임을 명시해줘야한다.
var anyArray = ["Eggs", 5] // error occured, add explicit type [Any] annotation
var anyArray: [Any] = ["Eggs", 5]
print(anyArray) // ["Eggs", 5]
6. Accessing and Modifying an Array
1 ) append(_:)
메서드는 배열의 마지막에 새 element
를 추가한다
var shoppingList: [String] = ["Eggs", "Milk"]
shoppingList.append("Flour")
print(shoppingList) // ["Eggs", "Milk", "Flour"]
2 ) +
연산자를 이용해 배열의 마지막에 새 element
를 추가할 수도 있다
var shoppingList = ["Eggs", "Milk", "Flour"]
shoppingList += ["Butter"]
print(shoppingList) // ["Eggs", "Milk", "Flour", "Butter"]
3 ) Subscript Syntax
를 이용해 배열의 값에 접근하거나, 수정할 수 있다
- 값에 접근하기
var shoppingList = ["Eggs", "Milk", "Flour", "Butter"]
print(shoppingList[0]) // Eggs
- 값 수정하기
var shoppingList = ["Eggs", "Milk", "Flour", "Butter"]
shoppingList[0] = "Organic eggs"
print(shoppingList) // ["Organic eggs", "Milk", "Flour", "Butter"]
shoppingList[1...3] = ["Organic milk", "Organic flour", "Premium butter"]
print(shoppingList) // ["Organic eggs", "Organic milk", "Organic flour", "Premium butter"]
4 ) insert(_:at:)
메서드는 element
를 배열의 특정 위치에 삽입한다
var shippingList = ["Organic eggs", "Organic milk", "Organic flour", "Premium butter"]
shoppingList.insert("Yeast", at: 2)
print(shoppingList) // ["Organic eggs", "Organic milk", "Yeast", "Organic flour", "Premium butter"]
5 ) removeLast()
메서드는 배열의 마지막 element
를 제거 후 해당 element
를 반환한다
var shoppingList = ["Organic eggs", "Organic milk", "Yeast", "Organic flour", "Premium butter"]
var removedElement = shoppingList.removeLast()
print(removedElement) // Premium butter
print(shoppingList) // ["Organic eggs", "Organic milk", "Yeast", "Organic flour"]
6 ) remove(at:)
메서드는 배열의 특정 위치의 element
를 제거 후 해당 element
를 반환한다
var shoppingList = ["Organic eggs", "Organic milk", "Yeast", "Organic flour"]
var secondElement = shoppingList.remove(at:1)
print(secondElement) // Organic milk
print(shoppingList) // ["Organic eggs", "Yeast", "Organic flour"]
7 ) removeAll()
메서드 또는 []
를 이용해 배열을 완전히 비울 수 있다
var shoppingList = ["Organic eggs", "Yeast", "Organic flour"]
shoppingList.removeAll()
print(shoppingList) // []
var shoppingList = ["Organic eggs", "Yeast", "Organic flour"]
shoppingList = []
print(shoppingList) // []
7. Iterating Over an Array
let fruits = [
"Apple",
"Pear",
"Persimmon",
"Tangerine",
"Orange",
"Mango",
"Plum",
"Cherry"
]
1 ) for-in
반복문을 이용해 배열의 전체 elements 에 접근할 수 있다
for item in fruits {
print(item, terminator: " ")
}
Apple Pear Persimmon Tangerine Orange Mango Plum Cherry
2 )sorted(by:)
메서드를 이용하면 배열의 값을 기준으로 정렬 후 접근할 수 있다
// default, ascending order
for item in fruits.sorted() {
print(item, terminator: " ")
}
Apple Cherry Mango Orange Pear Persimmon Plum Tangerine
// ascending order
for item in fruits.sorted(by: <) {
print(item, terminator: " ")
}
Apple Cherry Mango Orange Pear Persimmon Plum Tangerine
// descending order
for item in fruits.sorted(by: >) {
print(item, terminator: " ")
}
Tangerine Plum Persimmon Pear Orange Mango Cherry Apple
3 ) index
가 필요하다면 enumerated()
메서드를 이용해 tuple
을 상수로 받아 index
와 value
모두에 접근할 수 있다
let fruits = [
"Apple",
"Pear",
"Persimmon",
"Tangerine",
"Orange",
"Mango",
"Plum",
"Cherry"
]
for (index, value) in fruits.enumerated() {
print("Item \(index + 1): \(value)")
}
Item 1: Apple
Item 2: Pear
Item 3: Persimmon
Item 4: Tangerine
Item 5: Orange
Item 6: Mango
Item 7: Plum
Item 8: Cherry
3. Sets (셋) 👩💻
Set
은 unique 한 elements 를 저장하는 collection 이다.
Swift 의 Set 타입은 Foundation
의 NSSet
클래스와 연결되고, 이를 확장해 Set 에서 NSSet 메서드를 사용할 수 있게 해준다.
따라서, import Foundation
을 하면 Set 을 캐스팅 하지 않고 NSSet 메서드를 사용
할 수 있다.
1. Hash Values for Set Types
Set 타입은 Hashable
프로토콜을 준수해야한다.
또한 Hash Value
는 Int
값으로 두 object
가 완전히 동일하면 Hash Value
역시 동일하며 a == b
가 성립된다.
2. Set Type Syntax
다음 두 가지 형태의 initializer syntax
를 사용할 수 있다.
var newSet = Set<Element>()
var newSet: Set<Element> = [elements...] // Do not use to create Empty Set.
아래서 다시 설명하겠지만
Set
은Shorthand Syntax
의 사용이 불가능하다.
3. Creating an Empty Set
var letters = Set<Character>()
Set 은 Empty Set
생성시 Shorthand Syntax
를 사용할 수 없다 (Array 의 Shorthand Syntax 와 구분이 불가능하다)
letters.insert("c")
letters.insert("d")
이제 letters 는 “c”, “d”를 순서대로 저장하고있다.
letters = []
이후 Empty Array Literal([]
)를 이용해 비우더라도 Set<Character>
타입은 변하지 않는다.
4. Creating a Set with an Array Literal
Shorthand Syntax
는 사용할 수 없지만 Array Literal
을 이용해 Set
을 생성할 수 있다.
var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]
Set
역시 Array literal 을 이용해 초기 데이터가 주어지는 경우 Type Inference
를 사용할 수 있다.
단, Array 와의 구분을 위해 Set
이라는 것은 명시해야한다.
var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"]
Array 와 달리 서로 다른 Type 의 데이터는 담을 수 없다.
var anySet: Set<Any> = ["ABC", 5, "DEF"] // type 'Any' does not conform to protocol 'Hashable'
5. Accessing and Modifying a Set
1 ) insert(_:)
메서드는 Set 에 새 element를 중복 없이
추가한다
var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"]
favoriteGenres.insert("Jazz")
print(favoriteGenres) // ["Hip hop", "Classical", "Rock", "Jazz"]
favoriteGenres.insert("Jazz")
print(favoriteGenres) // ["Hip hop", "Classical", "Rock", "Jazz"]
위 예제에서 "Jazz"
를 두 번 추가했지만, Set 은 unique
하기 때문에 여전히 4개의 element 만 갖는다.
2 ) remove(_:)
메서드는 동일한 element
를 제거 후 해당 element
의 Optional
을 반환한다 (동일한 element
가 없을 경우 nil
을 반환)
var favoriteGenres: Set = ["Rock", "Classical", "Hip hop", "Jazz"]
var removedElement = favoriteGenres.remove("Hip hop")
print(removedElement as Any) // Optional("Hip hop")
print(favoriteGenres) // ["Classical", "Jazz", "Rock"]
var favoriteGenres: Set = ["Rock", "Classical", "Hip hop", "Jazz"]
var returnNil = favoriteGenres.remove("Funk")
print(returnNil as Any) // nil
3 ) removeAll()
메서드 또는 Empty Array Literal []
를 이용해 Set
을 완전히 비울 수 있다
var favoriteGenres: Set = ["Rock", "Classical", "Hip hop", "Jazz"]
favoriteGenres.removeAll()
print(favoriteGenres) // []
var favoriteGenres: Set = ["Rock", "Classical", "Hip hop", "Jazz"]
favoriteGenres = []
print(favoriteGenres) // []
6. Iterating Over a Set
let fruits: Set = [
"Apple",
"Pear",
"Persimmon",
"Tangerine",
"Orange",
"Mango",
"Plum",
"Cherry"
]
1 ) for-in
반복문을 이용해 Set 의 전체 elements 에 접근할 수 있다
for item in fruits {
print(item, terminator: " ")
}
Orange Persimmon Mango Apple Tangerine Pear Cherry Plum
Set 을 생성할 때 입력한 Array Literal 과는 순서가 다르다. Set 은 순서가 없는 Collection
이기 때문이다.
하지만 이미 생성된 Instance
는 다시 접근해도 동일한 순서 를 갖는다.
for item in fruits {
print(item, terminator: " ")
}
Orange Persimmon Mango Apple Tangerine Pear Cherry Plum
반면, 동일한 코드로 생성한 했지만 fruits2
는 fruits
와 접근시 순서가 다르다. 서로 다른 Instance
이기 때문이다.
let fruits2: Set = [
"Apple",
"Pear",
"Persimmon",
"Tangerine",
"Orange",
"Mango",
"Plum",
"Cherry"
]
for item in fruits2 {
print(item, terminator: " ")
}
Tangerine Plum Persimmon Apple Cherry Pear Orange Mango
Set 은 순서가 없기 때문에 Instance 가 생성될 때마다 순서가 변경된다.
하지만, 이미 생성한 Instance 를for-in
반복문으로 접근할 때는 다시 접근해도 동일한 순서를 갖는다.
즉, Instance 가 생성될 때 순서가 랜덤한 것이지 이미 생성된 Instance 에서 접근할 때 순서가 랜덤한 것은 아니다.
2 ) Set 은 Unordered Collection
이다. 따라서 특정 순서대로 정렬되길 원한다면 배열과 마찬가지로 sorted()
메서드를 이용한다
// default, ascending order
for item in fruits.sorted() {
print(item, terminator: " ")
}
Apple Cherry Mango Orange Pear Persimmon Plum Tangerine
// ascending order
for item in fruits.sorted(by: <) {
print(item, terminator: " ")
}
Apple Cherry Mango Orange Pear Persimmon Plum Tangerine
// descending order
for item in fruits.sorted(by: >) {
print(item, terminator: " ")
}
Tangerine Plum Persimmon Pear Orange Mango Cherry Apple
3 ) 배열과 마찬가지로 index
가 필요하다면 enumerated()
메서드를 이용해 tuple
을 상수로 받아 index
와 value
모두에 접근할 수 있다
단, 배열과 다른 점은 매번 접근 순서가 달라지므로 일정한 순서를 원한다면 정렬과 함께 사용해야한다
let fruits = [
"Apple",
"Pear",
"Persimmon",
"Tangerine",
"Orange",
"Mango",
"Plum",
"Cherry"
]
for (index, value) in fruits.sorted().enumerated() {
print("Item \(index + 1): \(value)")
}
Item 1: Apple
Item 2: Cherry
Item 3: Mango
Item 4: Orange
Item 5: Pear
Item 6: Persimmon
Item 7: Plum
Item 8: Tangerine
7. Performing Set Operations
두 Set 컬렉션 사이에 다음과 같은 수학적 연산을 수행할 수 있다.
Fundamental Set Operations
- intersection (교집합)
- symmetric difference (대칭차집합)
- union (합집합)
- difference of sets (차집합)
let oddDigits: Set = [1, 3, 5, 7, 9]
let evenDigits: Set = [0, 2, 4, 6, 8]
let singleDigitPrimeNumbers: Set = [2, 3, 5, 7]
1 )intersection (교집합)
교집합은 intersection(_:)
메서드를 사용한다.
let intersection = oddDigits.intersection(evenDigits).sorted()
print(intersection) // []
2 ) symmetric difference (대칭차집합)
대칭차집합은 symmetricDifference(_:)
메서드를 사용한다.
let symmetricDifference = oddDigits.symmetricDifference(singleDigitPrimeNumbers).sorted()
print(symmetricDifference) // [1, 2, 9]
3 ) union (합집합)
합집합은 union(_:)
메서드를 사용한다.
let union = oddDigits.union(evenDigits).sorted()
print(union) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
4 ) difference of sets (차집합)
차집합은 subtracting(_:)
메서드를 사용한다.
let differenceOfSets = oddDigits.subtracting(singleDigitPrimeNumbers).sorted()
print(differenceOfSets) // [1, 9]
8. Set Membership and Equality
두 Set 간의 관계를 표현할 수 있다.
- Set a is a
superset of
Set b (Set a 는 Set b 의 상위집합이다). - Set b is a
subset of
Set a (Set b_는 _Set a 의 부분집합이다). - Set b and Set c are
disjoint
with one another (Set b 와 Set c 는 서로소 집합관계다).
let houseAnimals: Set = ["🐶", "🐱"]
let farmAnimals: Set = ["🐮", "🐔", "🐑", "🐶", "🐱"]
let cityAnimals: Set = ["🐦", "🐭"]
1 ) Equality (상동)
상동은 ==
(equal operator)를 사용한다.
print(houseAnimals == houseAnimals) // true
2 ) Superset (상위 집합)
Superset 은 isSuperset(of:)
메서드를 사용한다.
print(farmAnimals.isSuperset(of: houseAnimals)) // true
print(farmAnimals.isSuperset(of: cityAnimals)) // false
Superset 을 판단하는 또 다른 메서드 isStrictSuperset(of:)
가 있다.
print(farmAnimals.isStrictSuperset(of: houseAnimals)) // true
print(farmAnimals.isStrictSuperset(of: cityAnimals)) // false
위 두 결과를 보면 isSuperset(of:)
메서드와 isStrictSuperset(of:)
메서드는 동일해보인다.
하지만 다음 결과를 보면 차이점을 알 수 있다.
print(farmAnimals.isSuperset(of: farmAnimals)) // true
print(farmAnimals.isStrictSuperset(of: farmAnimals)) // false
isSuperset(of:)
메서드는 두 Set 이 동일한 경우에도Superset
관계를 인정한다.
isStrictSuperset(of:)
메서드는 두 Set 이 동일한 경우Superset
관계를 인정하지 않는다.
3 ) Subset (부분 집합)
Subset 은 isSubset(of:)
메서드를 사용한다.
print(houseAnimals.isSubset(of: farmAnimals)) // true
print(cityAnimals.isSubset(of: farmAnimals)) // false
Subset 을 판단하는 또 다른 메서드 isStrictSubset(of:)
가 있다.
print(houseAnimals.isStrictSubset(of: farmAnimals)) // true
print(cityAnimals.isStrictSubset(of: farmAnimals)) // false
마찬가지로 isStrictSubset(of:)
은 좀 더 엄격하게 Subset
여부를 검사한다.
print(farmAnimals.isSubset(of: farmAnimals)) // true
print(farmAnimals.isStrictSubset(of: farmAnimals)) // false
isSubset(of:)
메서드는 두 Set 이 동일한 경우에도Subset
관계를 인정한다.
isStrictSubset(of:)
메서드는 두 Set 이 동일한 경우Subset
관계를 인정하지 않는다.
4 ) Disjoint Sets (서로소 집합)
Disjoint 관계(서로소 집합)은 isDisjoint(with:)
메서드를 사용한다.
print(houseAnimals.isDisjoint(with: cityAnimals)) // true
print(houseAnimals.isDisjoint(with: farmAnimals)) // false
4. Dictionary (딕셔너리) 👩💻
Dictionary
는 Key: Value
쌍을 elements 로 저장하는 collection 이다.
이때 key 는 Set 과 마찬가지로 unique 하다.
Swift 의 Dictionary 타입은 Foundation
의 NSDictionary
클래스와 연결되고, 이를 확장해 Dictionary 에서 NSDictionary 메서드를 사용할 수 있게 해준다.
따라서, import Foundation
을 하면 Dictionary 을 캐스팅 하지 않고 NSDictionary 메서드를 사용
할 수 있다.
1. Hash Values for Dictionary Keys
Dictionary 타입의 Key
는 Set 타입의 Value 처럼 Hashable
프로토콜을 준수해야한다.
따라서, Dictionary 는 동일한 Value
는 가질 수 있지만 동일한 Key
는 가질 수 없다.
2. Dictionary Type Syntax
다음 두 가지 형태의 initializer syntax
를 사용할 수 있다.
var someDictionary = Dictionary<Key, Value>()
var someDictionary = [Key: Value]() // Dictionary Type Shorthand Syntax (딕셔너리의 축약형 문법)
var someDictionary: [Key: Value] = [:] // Dictionary Type Shorthand Syntax (딕셔너리의 축약형 문법)
3. Creating an Empty Dictionary
var someDictionary: [Int: Strint] = [:]
Shorthand Syntax
를 이용해 빈 Dictionary 를 생성했다.
someDictionary[1] = "Apple"
someDictionary[2] = "Google"
print(someDictionary) // [1: "Apple", 2: "Google"] or [2: "Google", 1: "Apple"] because `Dictionary` is an unordered collection.
이제 someDictionary 는 1: "Apple"
, 2: "Google"
를 순서 없이 저장하고있다.
someDictionary = [:]
print(someDictionary) // [:]
print(type(of: someDictionary)) // Dictionary<Int, String>
Empty Dictionary Literal([:]
)를 이용해 someDictionary 를 다시 Empty Dictionary
로 만들더라도 [Int: String]
타입은 변하지 않는다.
4. Creating a Dictionary with a Dictionary Literal
var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
print(airports) // ["DUB": "Dublin", "YYZ": "Toronto Pearson"]
만약 위와 같이 Dictionary Literal
의 Key: Value
쌍이 한 가지 타입으로 구성되었다면, Swift 는 해당 딕셔너리의 타입을 추론한다.
var airports = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
print(airports) // ["DUB": "Dublin", "YYZ": "Toronto Pearson"]
Dictionary 는 Value
에 2 가지 이상의 타입을 저장 할 수 있다. 하지만 이 경우 Type Inference 는 사용할 수 없다.
반드시 [Key: Any]
타입을 명시 해줘야한다.
또한 Any
가 허용되는 것은 Value
만이다. Key
는 저장하려는 두 Key 가 모두 Hashable 하더라도
explicit type annotation
으로 선언하기 위해서는 Any
로 선언해야하는데, 이 Any
는 Non-Hashable
이기 때문이이다.
이는 Set 이 Any 타입으로 선언될 수 없는 것과 같다. 즉, [String: Any]
는 가능 하지만 [Any: String]
은 불가능 하다.
var airports = ["YYZ": "Toronto Pearson", "ZIP-CODE": 6301] // error occured, add explicit type [String: Any] annotation
var airports: [Any: String] // error: type 'Any' does not conform to protocol 'Hashable'
var airports: [String: Any] // This type is allowed.
var airports: [String: Any] = ["YYZ": "Toronto Pearson", "ZIP-CODE": 6301]
print(airports) // ["ZIP-CODE": 6301, "YYZ": "Toronto Pearson"]
5. Accessing and Modifying a Dictionary
1 ) Subscript Syntax
를 이용해 딕셔너리의 값에 접근하거나 추가, 수정, 삭제할 수 있다
Array 는 Subscript Syntax 를 이용해 값을 추가하려고 하면 Fatal error: Index out of range
가 발생해 접근
과 수정
만 가능하지만,
Dictionary 는 Subscript Syntax
를 이용해 값에 접근
, 수정
하는것은 물론, 추가
도 할 수 있다.
- 값에 접근하기
var shoppingList: [String: Int] = ["Eggs": 4500, "Milk": 3200]
print(shoppingList["Eggs"] as Any) // Optional(4500)
print(shoppingList["Eggs"] ?? 0) // 4500
Array 는 Ordered Collection
으로 배열의 크기를 통해 접근 가능한 Index
를 모두 정확히 알 수 있다.
즉, Array 는 값에 정확히 접근이 가능하기 때문에 Optional 이 아닌 정확한 값을 반환 한다.
하지만 Dictionary 는 Unordered Collection
으로 크기는 알 수 있지만 접근 가능한 Key
를 정확히 알 수 없다.
따라서 Key 가 존재할 경우 Optional(Value)를 반환하고,
없을 경우 nil을 반환한다.
- 값 수정하기
var shoppingList: [String: Int] = ["Eggs": 4500, "Milk": 3200]
shoppingList["Milk"] = 4000
print(shoppingList["Milk"] as Any) // Optional(4000)
Subscript Syntax 로 주어진 Key 가 딕셔너리 내에 존재할 경우 값을 업데이트한다.
- 값 추가하기
var shoppingList: [String: Int] = ["Eggs": 4500, "Milk": 3200]
shoppingList["Flour"] = 3600
print(shoppingList) // ["Flour": 3600, "Eggs": 4500, "Milk": 3200]
Subscript Syntax 로 주어진 Key 가 딕셔너리 내에 존재하지 않을 경우 딕셔너리에 추가한다.
- 값 삭제하기
var shoppingList: [String: Int] = ["Eggs": 4500, "Milk": 3200]
shoppingList["Milk"] = nil
print(shoppingList) // ["Eggs": 4500]
Subscript Syntax 로 주어진 Key 가 딕셔너리 내에 존재할 때 nil
을 Value
로 주입하면 딕셔너리에서
제거된다.
2 ) updateValue(_:forKey:)
메서드를 이용해 딕셔너리를 수정
, 추가
할 수 있다
Subscript Syntax 를 이용한 방법과 다른 점은 updateValue(_:forKey:)
메서드는 수정
, 추가
하면서
Optional(Old Value) 또는 nil을
반환한다는 것이다. 따라서 값이 실제로 업데이트 되었는지를 확인할 수 있다.
- 값 수정하기
var shoppingList: [String: Int] = ["Eggs": 4500, "Milk": 3200]
shoppingList.updateValue(4000, forKey: "Milk")
print(shoppingList["Milk"] as Any) // Optional(4000)
var shoppingList: [String: Int] = ["Eggs": 4500, "Milk": 3200]
if let oldValue = shoppingList.updateValue(4000, forKey: "Milk") {
print("The old value for Milk was \(oldValue).")
print("The current value for Milk is \(shoppingList["Milk"]!).")
}
The old value for Milk was 3200.
The current value for Milk is 4000.
updateValue(_:forKey:)
메서드는conditional binding
을 사용할 수 있다.
var shoppingList: [String: Int] = ["Eggs": 4500, "Milk": 3200]
if let oldValue = shoppingList["Milk"] = 4000 { // error: initializer for conditional binding must have Optional type, not '()'
print("The old value for Milk was \(oldValue).")
print("The current value for Milk is \(shoppingList["Milk"]!).")
}
Subscript Syntax 는 아무 값도 반환하지 않기 때문에
conditional binding
을 사용할 수 없다.
- 값 추가하기
var shoppingList: [String: Int] = ["Eggs": 4500, "Milk": 3200]
shoppingList.updateValue(3600, forKey: "Flour")
print(shoppingList) // ["Milk": 3200, "Flour": 3600, "Eggs": 4500]
위에서 Subscript Syntax 로 값을 추가한 것과 다른 점은 updateValue(_:forKey:)
메서드는
nil을 반환한다는 것이다
(만약 이미 존재한다면 추가가 아닌 수정으로 작동하고 Optional(Old Value) 를 반환).
var shoppingList: [String: Int] = ["Eggs": 4500, "Milk": 3200]
if let oldValue = shoppingList.updateValue(3600, forKey: "Flour") {
print("The old value for Flour was \(oldValue).")
print("The current value for Flour is \(shoppingList["Flour"]!).")
} else {
// cannot use oldValue because of else-clause
print("The flour was not exist.")
print("The current value for Flour is \(shoppingList["Flour"]!).")
}
The flour was not exist.
The current value for Flour is 3600.
nil 을 반환했기 때문에 else-clause 로 넘어갔다.
var shoppingList: [String: Int] = ["Eggs": 4500, "Milk": 3200]
let oldValue = shoppingList.updateValue(3600, forKey: "Flour")
print(oldValue as Any) // nil
print(shoppingList) // ["Milk": 3200, "Eggs": 4500, "Flour": 3600]
위 예제를 실행하면 nil 이 반환된 것을 확인할 수 있다.
3 ) removeValue(forKey:)
메서드를 이용해 딕셔너리를 제거
할 수 있다
var shoppingList: [String: Int] = ["Eggs": 4500, "Milk": 3200]
shoppingList.removeValue(forKey: "Milk")
print(shoppingList) // ["Eggs": 4500]
마찬가지로 위에서 Subscript Syntax 로 값을 제거한 것과 다른 점은 removeValue(forKey:)
메서드는 Optional(Old Value)을 반환한다는 것이다.
var shoppingList: [String: Int] = ["Eggs": 4500, "Milk": 3200]
if let oldValue = shoppingList.removeValue(forKey: "Milk") {
print("The removed shopping list milk price was \(oldValue).")
print("The milk is not exist any more.")
}
The removed shopping list milk price was 3200.
The milk is not exist any more.
4 ) removeAll()
메서드 또는 [:]
을 이용해 딕셔너리를 완전히 비울 수 있다
var shoppingList: [String: Int] = ["Eggs": 4500, "Milk": 3200]
shoppingList.removeAll()
print(shoppingList) // [:]
var shoppingList: [String: Int] = ["Eggs": 4500, "Milk": 3200]
shoppingList = [:]
print(shoppingList) // [:]
6. Iterating Over a Dictionary
let fruits = [
"Apple": 4200,
"Pear": 6800,
"Persimmon": 3400,
"Tangerine": 2800,
"Orange": 4300,
"Mango": 5100,
"Plum": 7100,
"Cherry": 8500
]
1 ) for-in
반복문을 이용해 Dictionary 의 전체 elements 에 접근할 수 있다
for element in fruits {
print(element)
}
(key: "Persimmon", value: 3400)
(key: "Tangerine", value: 2800)
(key: "Orange", value: 4300)
(key: "Apple", value: 4200)
(key: "Pear", value: 6800)
(key: "Plum", value: 7100)
(key: "Cherry", value: 8500)
(key: "Mango", value: 5100)
Dictionary 는 Iterator 의 element 를 상수로 받아 위와 같이 Key: Value
쌍을 하나의 element 로 접근하게된다.
따라서 각각의 Key
와 Value
에 접근하고 싶다면 다음과 같이 접근할 수 있다.
for element in fruits {
print("\(element.key)'s price is \(element.value)won.")
}
Persimmon's price is 3400won.
Plum's price is 7100won.
Mango's price is 5100won.
Cherry's price is 8500won.
Tangerine's price is 2800won.
Apple's price is 4200won.
Pear's price is 6800won.
Orange's price is 4300won.
하지만 Key
, Value
라고 쓰는 것은 가독성 측명에서 좋지 않다.
다음과 같이 element 를 tuple
로 비구조화(destructuring) 시키면 가독성도 높이고 더욱 쉽게 접근이 가능하다.
for (goods, price) in fruits {
print("\(goods)'s price is \(price)won.")
}
Tangerine's price is 2800won.
Orange's price is 4300won.
Apple's price is 4200won.
Plum's price is 7100won.
Persimmon's price is 3400won.
Mango's price is 5100won.
Cherry's price is 8500won.
Pear's price is 6800won.
2 ) Key 또는 Value 둘 중 하나만 필요할 경우 다음과 같이 접근 가능하다
for goods in fruits.keys {
print(goods, terminator: " ")
}
Plum Pear Cherry Persimmon Apple Orange Tangerine Mango
for price in fruits.values {
print(price, terminator: " ")
}
5100 4200 4300 6800 8500 3400 2800 7100
3 ) Dictionary 는 Unordered Collection
이다. 따라서 특정 순서대로 정렬되길 원한다면 배열과 마찬가지로 sorted()
메서드를 이용한다
// default, ascending order
for goods in fruits.keys.sorted() {
print(goods, terminator: " ")
}
Apple Cherry Mango Orange Pear Persimmon Plum Tangerine
// ascending order
for goods in fruits.keys.sorted(by: <) {
print(goods, terminator: " ")
}
Apple Cherry Mango Orange Pear Persimmon Plum Tangerine
for goods in fruits.keys.sorted(by: >) {
print(goods, terminator: " ")
}
Tangerine Plum Persimmon Pear Orange Mango Cherry Apple
4 ) sorted(by:)
에 closure
를 사용하면 tuple
로 받는 상수 역시 손쉽게 정렬된 순서로 받을 수 있다
// ascending order by keys
for (goods, price) in fruits.sorted(by: {$0.0 < $1.0}) {
print("\(goods)'s price is \(price)won.")
}
Apple's price is 4200won.
Cherry's price is 8500won.
Mango's price is 5100won.
Orange's price is 4300won.
Pear's price is 6800won.
Persimmon's price is 3400won.
Plum's price is 7100won.
Tangerine's price is 2800won.
// descending order by values
for (goods, price) in fruits.sorted(by: {$0.1 > $1.1}) {
print("\(goods)'s price is \(price)won.")
}
Cherry's price is 8500won.
Plum's price is 7100won.
Pear's price is 6800won.
Mango's price is 5100won.
Orange's price is 4300won.
Apple's price is 4200won.
Persimmon's price is 3400won.
Tangerine's price is 2800won.
Reference
- “Collection Types.” The Swift Programming Language Swift 5.7. accessed Oct. 3, 2022, Swift Docs Chapter 3 - Collection Types.
- “RandomAccessCollection.” Apple Developer Documentation. accessed Oct. 3, 2022, Apple Developer Documentation - Swift/Swift Standard Library/Collections.
- “RandomAccessCollection Implementations.” Apple Developer Documentation. accessed Oct. 3, 2022, Apple Developer Documentation - Swift/Array/RandomAccessCollection Implementations.