안녕하세요 :) 소들입니다
이번 포스팅에선 딕셔너리를 사용할 때 알아두면 편한 메서드들을 좀 정리해보려고 해요!!!
원래 설명충이긴 한데, 이번 포스팅만큼은 단순 명료하게 가겠슴니다!!
(물론 설명할 게 있는 부분은 설명충임 :))
모든 포스팅은 편의 말투로 합니다~!!
.
.
.
자 먼저..!!!
Swift의 딕셔너리 특징에 대해서 간!!!딴!!!!히!!!! 먼저 알고 가겠움 :)
🔸Key : Value가 함께 저장되는 자료구조이다
🔸정렬되지 않은 컬렉션이다
(따라서 딕셔너리를 print할 경우, 삽입 순서에 상관 없이 뒤죽박죽 나온다)
🔸값은 중복 가능하지만, 키는 중복되면 안 된다
🔸Swift는 형식에 민감쓰 하기 때문에, 모든 Key의 자료형은 같아야 하고,
마찬가지로 모든 Value의 자료형도 같아야 한다
끄...읕... 🌝 이 정돈 기본이니 알아둡시다....... :D
이제 딕셔너리에서 사용하는 메서드에 대해 다루겠음 :)
아 참고로, 딕셔너리도 배열과 같은 Collection Type이고, 때문에
구조체로 Stack에 저장됨! 다만, NSDictionary란 클래스도 지원함(Objective-C)
1. 딕셔너리 생성하기
// 1. 타입 추론으로 생성하기
var dict1 = ["height": 165, "age" : 100]
var dict2 = [:] // error! 타입 추론으론 빈 딕셔너리 생성 불가
// 2. 타입 Annotation으로 생성하기
var dict3: [String: Int] = [:] // 빈 딕셔너리 생성
var dict4: [String: Int] = ["height": 165, "age" : 100]
// 3. 생성자로 생성하기
var dict5 = Dictionary<String, Int>() // :이 아닌 ,로 명시
var dict6 = [String: Int]()
|
보통 간편한 1번이나 2번의 방법을 많이 사용함!!!
나 같은 경우엔 Type Annotation을 좋아해서 2번을 많이 씀 :)
녀러분 Swift는 머라거?? 타입에 굉~~~~장히 민감한 언어임!!!
선언과 동시에 Type을 꼭 명시하거나 추론할 수 있게 해주어야 하고,
해당 Type으로 된 값만 딕셔너리에 저장할 수 있음!!!
따라서 만약 난 딕셔너리 한 개에 여러 타입의 Value를 저장하고 싶은데???
혹은 난 런타임 시점에 타입을 알 수 있는데????라고 할 수 있잖음??
Key 값의 Type을 Any로 선언하거나, Objective-C의 클래스인 NSDictionary를 사용하면 됨
// 4. 여러 타입을 저장하는 딕셔너리 생성하기
var dict7: [String: Any] = ["name": "Sodeul", "age": 100]
var dict8: NSDictionary = ["name": "Sodeul", "age": 100]
|
Value 같은 경우, 배열 때와 마찬가지로 Any라는 자료형을 쓰면 됨!!!
호옹..? 근데 나는 Key 값도 여러 타입 받고 싶은데..? 해서 Any로 선언할 경우,
다음과 같은 에러를 볼 수 있음
Any가 Hashable 프로토콜을 준수하지 않는단 말임..!
이 포스팅을 보면 알겠지만, 딕셔너리는 Key 값을 해시한 것을 토대로 데이터를 저장하기 때문에
딕셔너리의 Key 값은 아무나 올 수 없음!!!!!!!!! 무조건 Hashable이란 프로토콜을 준수하는 자료형만 Key 값에 올 수 있음
때문에 Any도 올 수 없는 것이고, 만약 커스텀 자료형을 만든다면, Hashable 프로토콜을 준수해야만,
Dicitonary의 Key 값으로 사용할 수 있음 :)
배열에서도 말했듯, Any를 남발하는 것은 정적 바인딩 언어인 Swift를....
동적 바인딩 시키는 것이기 때문에,,,,, 타입에 민감한 Swift를 웬만해선 지켜줍시다.. :)
2. 딕셔너리 갯수 확인하기
var dict1 = ["height": 165, "age" : 100]
let count: Int = dict1.count // 딕셔너리 갯수 확인 : 3
let isEmpty: Bool = dict1.isEmpty // 딕셔너리 비었는지 확인 : false
|
만약 딕셔너리가 비었는지를 확인하고 싶다면
dict1.count == 0 이 구문보단, dict1.isEmpty를 사용합시다 :)
3. 딕셔너리 요소에 접근하기
var dict1 = ["height": 165, "age" : 100]
// 1. 반환 값 - Optional Type
let height = dict1["height"] // Optional(165)
let weight = dict1["weight"] // nil
// 2. 반환 값 - Non Optional Type
let height = dict1["height", default: 150] // 165
let weight = dict1["weight", default: 200] // 200
|
딕셔너리의 경우, Subscript로 요소에 접근하면
기본 반환값이 Optional Type이기 때문에 (해당 Key 값이 없을 때를 대비)
따라서, 만약 Optional Type이 싫다!!!!!!하면 default 값을 직접 명시하면 됨!
그럼 반환 값이 Non-Optional Type임!
4. 딕셔너리에 요소 추가하기
var dict1 = ["height": 165, "age" : 100]
// 1. Subscript로 추가하기
dict1["weight"] = 100 // 해당 Key가 없다면, 추가 (insert)
dict1["height"] = 200 // 해당 Key가 있다면, Value 덮어쓰기 (update)
// 2. updateValue(:forKey)
dict1.updateValue(100, forKey: "weight") // 해당 Key가 없다면, 추가하고 nil 리턴 (insert)
dict1.updateValue(200, forKey: "height") // 해당 Key가 있다면, Value 덮어쓰고 덮어쓰기 전 값 리턴 (update)
|
Subscript의 경우, insert인지 update인지 알 수 없지만,
updateValue의 경우, 리턴 값을 통해 insert인지 update인지를 알 수 이씀!
(참고로 Insert와 upsert를 상황에 따라 해주는 것을 upsert라고 함)
5. 딕셔너리에 요소 삭제하기
var dict1 = ["height": 165, "age" : 100]
// 1. Subscript로 삭제하기 (nil 대입하기)
dict1["weight"] = nil // 해당 Key가 없어도 에러 안남
dict1["height"] = nil // 해당 Key가 있다면, 해당 Key-Value 삭제
// 2. removeValue(forKey:)
dict1.removeValue(forKey: "weight") // 해당 Key가 없다면, nil 반환
dict1.removeValue(forKey: "age") // 해당 Key가 있다면, 해당 Key-Value 삭제 후 삭제된 Value 반환 : Optional(100)
// 3. removeAll() : 전체 삭제하기
dict1.removeAll()
|
6. Key, Value 나열하기
var dict1 = ["height": 165, "age" : 100]
// 1. Key 모두 나열하기
dict1.keys // "height, "age"
dict1.keys.sorted() // "age", "height
// 2. Value 모두 나열하기
dict1.values // 165, 100
dict1.values.sorted() // 100, 165
|
정렬도 가능!!!!!!!!!!!!
keys, values는 찍을 때마다 다르게 나올테니 당황 노노
(딕셔너리는 정렬되지 않는 Collection Type)
7. 딕셔너리 비교하기
var dict1 = ["height": 165, "age" : 100]
var dict2 = ["height": 165, "age" : 100]
var dict3 = ["Height": 165, "Age" : 100]
var dict4 = ["name": "sodeul", "address" : "Suwon"]
dict1 == dict2 // true
dict1 == dict3 // false (대소문자 다름)
dict1 == dict4 // false (모든 Key-Vlaue 다름)
|
비교 연산자로 비교할 수 있으나, 모든 Key와 Value가 정확히 모두 일치해야만
true가 됨!!!! 대소문자도 비교하기 때문에, dict1과 dict3은 다른 딕셔너리임!!!
8. 딕셔너리 요소 검색하기
var dict1 = ["height": 165, "age" : 100]
let condition: ((String, Int)) -> Bool = {
$0.0.contains("h")
}
// 1. contains(where:) : 해당 클로저를 만족하는 요소가 하나라도 있을 경우 true
dict1.contains(where: condition) // true
// 2. first(where:) : 해당 클로저를 만족하는 첫 번쨰 요소 튜플로 리턴 (딕셔너리는 순서가 없기 때문에, 호출할 때마다 값이 바뀔 수 있음)
dict1.first(where: condition) // Optional((key: "height", value: 165))
// 3. filter : 해당 클로저를 만족하는 요소만 모아서 새 딕셔너리로 리턴
dict1.filter(condition) // ["height": 165]
|
자, 여기서 중요한 거!!!!!!!!!! 딕셔너리 요소 검색할 때는
클로저를 이용해서 검색하는데,
이때 클로저의 파라미터 타입은 내가 지정한 딕셔너리의 타입을 갖는
튜플이어야 하고!! 반환 타입은 무조건 Bool이어야 함!!!!!!!!!1
만약 [String: String] 타입의 딕셔너리라면,
((String, String)) -> Bool
클로저를 이렇게 작성 하셔야 함..........:D
+ 만약 딕셔너리 순회(for - in, forEach) 등에 대해 알고 싶으신 분은
이 포스팅을 참조해주센~~
.
.
.
딕셔너리를 사용할 때 어쩌면 필수고 어쩌면 알아두면 좋은 메서드들 정리 끝 :)
또한 더 많은 메서드들을 알게되면 추가 할게영 :D
읽으시는 모든 분께 도움이 됐길 ~.~
잘못된 내용, 피드백, 궁금증은 언제나 댓글 주세요 💩
그럼 프젝하러 가야해서 20,000
'iOS > Swift' 카테고리의 다른 글
Swift) 열거형(Enumeration) 기초편 (10) | 2021.02.16 |
---|---|
Swift) Set - 자주 사용하는 메서드 (2) | 2021.02.09 |
Swift) for - in / forEach 제대로 알고 쓰기 (4) | 2021.01.12 |
Swift) Array - 자주 사용하는 메서드 (4) | 2021.01.08 |
Swift) 클로저(Closure) 정복하기(3/3) - 클로저와 ARC (40) | 2020.12.22 |