static Dictionary DictionaryGenerator?

This what I have to do:


enum ItemKind : Int {
    case    All
    case    Mine
    case    InUse
    case    Archive


    static let all = [ItemKind.All, ItemKind.Mine, ItemKind.InUse, ItemKind.Archive]
    static let strings = ["All", "Mine", "In Use", "Archive"]
    static let values:[String:ItemKind] = [
        strings[ItemKind.All.rawValue]: ItemKind.All
    ,   strings[ItemKind.Mine.rawValue]: ItemKind.Mine
    ,   strings[ItemKind.InUse.rawValue]: ItemKind.InUse
    ,   strings[ItemKind.Archive.rawValue]: ItemKind.Archive
    ]


    var description: String {
        return ItemKind.strings[self.rawValue]
    }
}


This what I would like to do:


enum ItemKind : Int {
    case    All
    case    Mine
    case    InUse
    case    Archive


    static let all = [ItemKind.All, ItemKind.Mine, ItemKind.InUse, ItemKind.Archive]
    static let strings = ["All", "Mine", "In Use", "Archive"]
    static let values:[String:ItemKind] = all.map {
        /// ???
        ($0.description, $0)
        /// ??? or something
    }


    var description: String {
        return ItemKind.strings[self.rawValue]
    }
}


Anyway to tweak the latter such that I can avoid hard-coding the dictionary values as I am forced to do in the former?


I had a look at Dictionary.generate but this an instance method and I would need a static one. Or at least an initializer.

(for unrelated reasons I need the `ItemKind` enum to based off `Int` not `String`)

Accepted Reply

How is this?

enum ItemKind : Int {
    case    All
    case    Mine
    case    InUse
    case    Archive
   
    static let all = [ItemKind.All, ItemKind.Mine, ItemKind.InUse, ItemKind.Archive]
    static let values:[String:ItemKind] = {
        var result: [String: ItemKind] = [:]
        all.forEach {
            result[$0.description] = $0
        }
        return result
    }()
   
    var description: String {
        return String(self)
    }
}
print(ItemKind.values) //->["Mine": ItemKind.Mine, "All": ItemKind.All, "InUse": ItemKind.InUse, "Archive": ItemKind.Archive]

Replies

How is this?

enum ItemKind : Int {
    case    All
    case    Mine
    case    InUse
    case    Archive
   
    static let all = [ItemKind.All, ItemKind.Mine, ItemKind.InUse, ItemKind.Archive]
    static let values:[String:ItemKind] = {
        var result: [String: ItemKind] = [:]
        all.forEach {
            result[$0.description] = $0
        }
        return result
    }()
   
    var description: String {
        return String(self)
    }
}
print(ItemKind.values) //->["Mine": ItemKind.Mine, "All": ItemKind.All, "InUse": ItemKind.InUse, "Archive": ItemKind.Archive]

This certainly beats my cumbersome/nitty-gritty way!


But I was hoping for some magic along the line:


static let values:[String:ItemKind] = all.mapThatReturnsADictionary {
    lambdaThatCreatesOneDictEntryFrom($0)
}


It would be a tad disapointing if there wasn't a "Swifty" way to do this ...

Until Swift includes something you can do it in "Swifty" way, you can implement your own with less "Swifty" (?) way:

extension Array {
    func mapThatReturnsADictionary<KeyType:Hashable>(lambdaThatCreatesOneDictEntryFrom:(Element)->(KeyType,Element))->[KeyType:Element] {
        var result: [KeyType:Element] = [:]
        self.forEach {elt in
            let (key,value) = lambdaThatCreatesOneDictEntryFrom(elt)
            result[key] = value
        }
        return result
    }
}
enum ItemKind : Int {
    case    All
    case    Mine
    case    InUse
    case    Archive

    static let all: [ItemKind] = [.All, .Mine, .InUse, .Archive]
    static let values: [String: ItemKind] = all.mapThatReturnsADictionary{($0.description,$0)}

    var description: String {
        return String(self)
    }
}