将 `(String, Int)...` 可变参数函数转换为 ExpressibleByDictionaryLiteral 的字典

问题描述 投票:0回答:1

我有一些对象当前是通过采用数组或字典的单参数

init
函数初始化的。

我意识到我可以使用

ExpressibleByArrayLiteral
ExpressibleByDictionaryLiteral
来代替。但我相信我仍然需要非文字初始化器,也许直到实现在 Swift 中将数组传递给具有可变数量参数的函数

struct ArrayStruct: ExpressibleByArrayLiteral {
    typealias ArrayLiteralElement = Int
    
    let array: [Int]
    
    init(array: [Int]) {
        self.array = array
    }
    
    init(arrayLiteral elements: Int...) {
        self.init(array: elements) // ok
    }
}

struct DictStruct: ExpressibleByDictionaryLiteral {
    typealias Key = String
    typealias Value = Int
    
    let dict: [String : Int]
    
    init(dict: [String : Int]) {
        self.dict = dict
    }
    
    init(dictionaryLiteral elements: (String, Int)...) {
        self.init(dict: elements) // Cannot convert value of type '(String, Int)...' to expected argument type '[String : Int]'
    }
}

我希望初始化程序都调用相同的代码路径,因此变量 init 可以调用集合 init,反之亦然。

对于数组,我可以将

Int...
可变参数直接传递给现有的
[Int]
初始值设定项。为什么这只适用于数组?

但这对词典不起作用。现有的初始化程序需要一个

[String : Int]
字典,但
ExpressibleByDictionaryLiteral
函数参数是
(String, Int)...

为什么这些“可通过数组/字典文字表达”首先给你一个可变参数,而不是数组/字典?这是一个文字数组...为什么它不给你一个数组?

如何将

(String, Int)...
转换为
[String : Int]

swift variadic-functions literals variadic
1个回答
0
投票

问题在于,从键值对列表到字典没有“明显”的转换。您必须决定如何处理重复项。它们是否是编程错误导致崩溃?你拿第一个吗?最后一个?以某种方式将它们结合起来?由您决定,Swift 支持所有这些方法。

例如,如果键不唯一(这对于文字来说不是一个坏主意),要使程序崩溃,您可以这样写:

init(dictionaryLiteral elements: (String, Int)...) {
    let dict = Dictionary(uniqueKeysWithValues: elements)
    self.init(dict: dict)
}

或者,要获取给定键的最后一个元素,您可以这样写:

init(dictionaryLiteral elements: (String, Int)...) {
    let dict = Dictionary(elements, uniquingKeysWith: { _, second in second })
    self.init(dict: dict)
}
© www.soinside.com 2019 - 2024. All rights reserved.