티스토리 뷰
문서를 보면 Dictionary 의 subscript 로 세개가 구현되어있다.
✓ subscript(Key) -> Value? // get set
✓ subscript(Key, default _: () -> Value) -> Value // get set
✓ subscript(Dictionary<Key, Value>.Index) -> Dictionary<Key, Value>.Element // get
3번째처럼 key-based subscript 가 아니라 index-based subscript 도 있는 줄 몰랐는데,
정리해두자!
[1] subscript(Key) -> Value?
- 문서
- 코드 구현
var responseMessages = [200: "OK",
403: "Access forbidden",
404: "File not found",
500: "Internal server error"]
// get
print(responseMessages[200]) // Optional("OK")
print(responseMessages[700]) // nil
// set
responseMessages[200] = (responseMessages[200] ?? "OK") + "✅"
responseMessages[401] = (responseMessages[401] ?? "Unauthorized") + "❌"
print(responseMessages) // [200: "OK✅", 401: "Unauthorized❌" ...]
[2] subscript(Key, default _: () -> Value) -> Value
- 문서
- 코드구현
key 가 존재하지 않으면 default value를 준다.
Accesses the value with the given key, falling back to the given default value if the key isn’t found.
var responseMessages = [200: "OK",
403: "Access forbidden",
404: "File not found",
500: "Internal server error"]
// get
print(responseMessages[200, default: "Unknown"]) // OK
print(responseMessages[700, default: "Unknown"]) // Unknown
// set
responseMessages[200, default: "OK"] += "✅"
responseMessages[401, default: "Unauthorized"] += "❌"
print(responseMessages) // [200: "OK✅", 401: "Unauthorized❌" ...]
실예제로 numberOfElements in Array (또는 Occurrences in Array) 를 구하는 데 편하게 쓸 수 있다.
이렇게 extension을 만들어서 사용했던 적이 있는데,
extension Array where Element: Hashable {
func numberOfElements() -> [Element: Int] {
var dic: [Element: Int] = [:]
for element in self {
dic[element, default: 0] += 1
}
return dic
}
}
let array = [10, 20, 10, 20, 30, 20]
array.numberOfElements() // [10: 2, 20: 3, 30: 1]
문서에도 비슷한 예제 (Use subscript while counting the occurrences of each letter in a string) 가 있다.
let message = "Hello, Elle!"
var letterCounts: [Character: Int] = [:]
for letter in message {
letterCounts[letter, default: 0] += 1
}
// letterCounts == ["H": 1, "e": 2, "l": 4, "o": 1, ...]
[3] subscript(Dictionary<Key, Value>.Index) -> Dictionary<Key, Value>.Element
- 문서
- 코드구현
index (Int가 아니라 Dictinary.Index 타입) 를 받아서 key-value pair (tuple) 를 리턴해준다.
var responseMessages = [200: "OK",
403: "Access forbidden",
404: "File not found",
500: "Internal server error"]
if let index = responseMessages.firstIndex(where: { $0.value == "OK" }) {
print(responseMessages[index]) // (key: 200, value: "OK")
}
문서에 있는 실예제라고 할 수 있는 코드도 첨부한다.
아래와 같이 collection-based operations 을 수행할 때, 이 subscript을 사용하면 좋다고 한다.
let countryCodes = ["BR": "Brazil", "GH": "Ghana", "JP": "Japan"]
if let index = countryCodes.firstIndex(where: { $0.value == "Japan" }) {
print(countryCodes[index])
print("Japan's country code is '\(countryCodes[index].key)'.")
} else {
print("Didn't find 'Japan' as a value in the dictionary.")
}
// Prints "(key: "JP", value: "Japan")"
// Prints "Japan's country code is 'JP'."
여기서 헷갈리면 안되는 점은 dic 이기때문에 array 의 firstIndex와 다르다는 점이다.
똑같은 value를 가진 key, value pair 를 추가하고 돌려봤을 때 출력값이 달라지는 것을 확인할 수 있다.
var responseMessages = [200: "OK",
✅ 201: "OK",
403: "Access forbidden",
404: "File not found",
500: "Internal server error"]
if let index = responseMessages.firstIndex(where: { $0.value == "OK" }) {
print(responseMessages[index]) // (key: 201, value: "OK")
}
추측컨데,,, 명목상(?) firstIndex 로 네이밍을 한 것 같다.
lastIndex 는 없고 코드구현을 봐도 OrderedDictionary 가 사용되지 않았기 때문이다.
만약 value가 아니라 key값으로 index 를 찾는다면
명확하게 index(forKey:) 를 사용하면 좋을 것 같다는 생각이 든다.
[3.1] KeyValuePairs
위에서 다룬 것처럼 key-value pairs 의 순서는 예측 불가능하다.
만약 ordered collection이 필요하고 딕셔너리 처럼 fast key lookup 이 필요하지 않다면
KeyValuePairs 를 대안으로 사용할 수 있다. (참고: 주석)
Swift-collections에서 OrderedDictionary 를 import 하지 않고
좀더 라이트하게 순서가 보장된 key value collection을 쓸 수 있는 방법이다.
위의 예제와 달리 KeyValuePairs 를 쓰면 항상 같은 결과가 나온다.
var responseMessages: KeyValuePairs = [200: "OK",
201: "OK",
403: "Access forbidden",
404: "File not found",
500: "Internal server error"]
if let index = responseMessages.firstIndex(where: { $0.value == "OK"}) {
print(responseMessages[index]) // (key: 200, value: "OK")
}
몇몇 연산들은 dictionary 를 사용하는 것보다 더 속도가 느리다.
예를들어 firstIndex(where:) 를 콜할 때는 collection 전체를 순회한다고 한다.
코드구현을 보면 배열 기반으로 되어있다.
+
KeyValuePairs 는 아래와 같은 특성 때문에 혼란이 좀 있을 수 있을 것 같다..
- Key가 Hashable 이 아니여도 됨.
- duplicates keys 도 허용함.
이건 dic이라고 생각안하고 아주 간단히 ordered dic 같은게(?) 필요할 때 써야할 것 같다.
'🍏 > Swift' 카테고리의 다른 글
[Swift] self in a closure in a closure (0) | 2023.07.11 |
---|---|
[Swift Collections] Heap (0) | 2023.05.20 |
[Swift] actor (0) | 2023.04.10 |
[Swift] Sendable (0) | 2023.04.08 |
[Swift] withTaskGroup, withThrowingTaskGroup (0) | 2023.03.17 |
- Total
- Today
- Yesterday
- flutter deep link
- ipad multitasking
- 플러터 얼럿
- Django Heroku Scheduler
- 장고 Custom Management Command
- Flutter Spacer
- cocoapod
- PencilKit
- Dart Factory
- flutter dynamic link
- Watch App for iOS App vs Watch App
- Python Type Hint
- 구글 Geocoding API
- flutter build mode
- ribs
- Django FCM
- Django Firebase Cloud Messaging
- 플러터 싱글톤
- 장고 URL querystring
- METAL
- drf custom error
- github actions
- flutter 앱 출시
- DRF APIException
- Sketch 누끼
- Flutter getter setter
- Flutter Text Gradient
- Flutter 로딩
- SerializerMethodField
- Flutter Clipboard
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |