Swift

Dictionary.init(uniqueKeysWithValues:)

GREEN.1229 2021. 8. 31. 19:30

안녕하세요. 그린입니다🟢

이번 포스팅에서는 Dictionary.init(uniqueKeysWithValues:)에 대해 학습해보겠습니다💁🏻

 

딕셔너리가 뭐에요??

우선 딕셔너리는 key와 value로 이루어진 데이터를 담는 컨테이너입니다.

특징이라하면 각 value는 고유의 유일한 key와 연결되어 있습니다.

딕셔너리는 array처럼 순서가 있지 않기에 각 물려있는 key값으로 value값을 찾을 수 있습니다.

 

즉 딕셔너리를 표현한다면 Dictionary<KeyType, ValueType>로 표현할 수 있습니다📑
그렇다면 딕셔너리의 키값은 고유의 값이니 Hashable 해야겠쬬!?

그런데 우리가 쓰는 딕셔너리의 키값은 대부분 swift에서 기본 제공하는 Int, String, enum 등등일겁니다!

해당 기본제공되는 자료형 타입들은 이미 Hashable해서 따로 지정하지 않고 쓰는거에요😀

 

딕셔너리를 간략히 소개한다 했는데 서두가 너무 길었어요!
그럼 본격적으로 오늘 학습하려한 딕셔너리를 초기화하는 방법에 대해 알아보겠습니다..!
다양한 방법이 있지만 저는 Dictionary.init(uniqueKeysWithValues:)에 대해 알아보려해요.

 

왜 Dictionary.init(uniqueKeysWithValues:)를 알려하죠?

어떠한 커스텀한 자료형이 있다고 가정합니다.

예를들어 아래와 같이 생각해볼 수 있겠어요!

let sampleData: [Sample] = [...]

struct Sample: {
  var title: String
  var subtitle: String
  var checked: Bool
  ...
}

이러한 커스텀한 타입의 데이터를 만약 서버의 API와 통신하려합니다.

서버의 API 필드값들은 정해진 Timestamp, Bool, Num, String, Map 등등.. 밖에 인식하지 못합니다.

즉 저대로 그냥 넘겨주면 안되겠죠?

지정된 API 필드 형태에 맞게 넘겨주어야합니다.

 

그러면 예를들어 가정해보겠습니다.

서버의 API 필드값이 map으로 [String:Bool]의 데이터들이 쫙~~ 있습니다.

이 데이터에 위의 sampleData에서 title과 checked의 정보만 가져와 서버로 넘겨주고 싶다면..?

 

먼저 저는 Dictionary.init(uniqueKeysWithValues:)를 사용하지 못하였을때는 아래와 같이 했습니다.

let convertedData = sampleData.map({ data -> [String:Bool] in
  guard let title = data.title else { return [:] }
  guard let checked = data.checked else { return [:] }
  return [title:checked]
})
.flatMap({ $0 })
.reduce([String:Bool]()){ (dict, tuple) in
  var updatedDict = dict
  updatedDict.updateValue(tuple.1, forKey: tuple.0)
  return updatedDict
}

이런식으로요😅

map을 거치게 되면 [[String:Bool]]로 어레이 맵 타입이 됩니다.

이걸 flatMap을 거치고 reduce를 거쳐 [String:Bool]으로 타입을 맞춰줍니다.

이렇게해도 물론 잘 동작하고 됩니다!!

 

그러나, 위와 같이하면 코드가 좀 복잡해지죠..?

이럴때 더 간단히 아예 생성할때 딕셔너리로 초기화 시켜버리는 겁니다.

let convertedData = sampleData.map({ data -> (String,Bool) in
  guard let title = data.title else { return ["",false] }
  guard let checked = data.checked else { return ["",false] }
  return (title:checked)
})

어때요 훨~씬 간략해졌죠?

저기서 String,Bool이 key와 value입니다. key/value 타이핑이 생략되었을뿐!

이렇게 한다라고 한다라면 map을 해줘도 [[String:Bool]]이 되지 않고 딕셔너리로 초기화 할 수 있습니다.

 

자.. 멀리 돌고 돌았지만 저는 현재 저럴때 간략하게 나타내고 싶어서 학습을 해보았어요!

당연히 더 다양하게 사용되겠죠😳

그런건 다음번에🤯

 

[참고자료]

https://developer.apple.com/documentation/swift/dictionary/3127165-init

 

Apple Developer Documentation

 

developer.apple.com