Swift/개념 & 응용

[Swift] Dictionary Grouping

유정주 2023. 3. 13. 14:20
반응형

서론

Array를 포함한 Collection를 Dictionary로 묶고 싶은 상황이 있습니다.

 

예를 들면, 아래와 같은 ItemType Enum이 있다고 합시다.

enum ItemType: Hashable, CustomStringConvertible {
    case old, new
    
    var description: String {
        switch self {
        case .old: return "old"
        case .new: return "new"
        }
    }
}

 

그리고 이 Enum을 가지고 있는 구조체 Item이 있어요.

struct Item: CustomStringConvertible {
    var name: String
    var type: ItemType
    
    var description: String {
        return name
    }
}

 

랜덤한 아이템 순서의 Item 배열인

let items: [Item] = [Item(name: "ID1", type: .new),
                     Item(name: "ID2", type: .old),
                     Item(name: "ID3", type: .old),
                     Item(name: "ID4", type: .new),
                     Item(name: "ID5", type: .new)]

에서 old 타입은 무슨 아이템이 있고, new 타입은 무슨 아이템이 있는지 궁금하다고 합시다.

 

이렇게 아이템을 분류하고 싶은 경우, Dictionary가 딱이죠.

type을 키로 사용하고, value에는 Item 배열을 사용하면 되니까요.

 

For문으로 만들기

먼저 흔하게 사용되는 for문입니다.

var dict1: [ItemType: [Item]] = [:]
for item in items {
    dict1[item.type, default: []].append(item)
}

배열의 아이템을 하나하나 딕셔너리에 넣는 방법이에요.

 

dict1을 출력해보면

[new: [ID1, ID4, ID5], old: [ID2, ID3]]

제대로 분류가 되었습니다.

따라서 이 방법도 틀린 건 아닙니다!

 

다만, 지금부터 소개드릴 방법은 짧고 명확하다는 장점이 있습니다.

 

Dictionary(grouping:by:)

이번 포스팅에서 소개드릴 방법은 Dictionary(grouping:by:) 입니다.

grouping에는 그룹화할 Sequnce를 전달하고,

by에는 딕셔너리의 Key로 사용할 타입을 전달합니다.

 

let dict2 = Dictionary(grouping: items, by: { $0.type })
//key-path 사용
//let dict2: [ItemType: [Item]] = Dictionary(grouping: items, by: \.type)

이렇게요. (타입은 위와 동일하게 [ItemType: [Item]] 입니다.)

 

dict2를 출력해보면

[new: [ID1, ID4, ID5], old: [ID2, ID3]]

훌륭하게 그룹화가 된 것을 볼 수 있습니다.

 

시간복잡도는 동일하지만

코드의 길이와 명확성이 증가했다는 걸 느낄 수 있을 겁니다.

이제는 반복문 대신 Dictionary(grouping:by:)를 사용해 봅시다!

 

감사합니다!

 

전체 코드

더보기
import UIKit

enum ItemType: Hashable, CustomStringConvertible {
    case old, new
    
    var description: String {
        switch self {
        case .old: return "old"
        case .new: return "new"
        }
    }
}

struct Item: CustomStringConvertible {
    var name: String
    var type: ItemType
    
    var description: String {
        return name
    }
}

let items: [Item] = [Item(name: "ID1", type: .new),
                     Item(name: "ID2", type: .old),
                     Item(name: "ID3", type: .old),
                     Item(name: "ID4", type: .new),
                     Item(name: "ID5", type: .new)]

var dict1: [ItemType: [Item]] = [:]
for item in items {
    dict1[item.type, default: []].append(item)
}
print("dict1: \(dict1)")

//var dict2: [ItemType: [Item]] = Dictionary(grouping: items, by: { $0.type })
var dict2: [ItemType: [Item]] = Dictionary(grouping: items, by: \.type)
print("dict2: \(dict2)")

 

참고

https://developer.apple.com/documentation/swift/dictionary/init(grouping:by:) 


아직은 초보 개발자입니다.

더 효율적인 코드 훈수 환영합니다!

공감 댓글 부탁드립니다.

 

 

반응형