Array.map() 生成“[T]”,而不是预期的上下文结果类型“[String: Any?]”

Array.map() produces '[T]', not the expected contextual result type '[String: Any?]'

我正在编写一个扩展来桥接 FirebaseDatabase 和 Eureka 之间的字典值。

private extension Dictionary {
    func firebaseFriendlyDictionary() -> [String: Any?] {
        return self.map({ (key: String, value: Any?) -> (String, Any?) in
            if value is NSDate {
                return (key, (value as! NSDate).timeIntervalSince1970)
            }
            return (key, value)
        })
    }
}

但是当我尝试构建时抛出这个错误:

map produces '[T]', not the expected contextual result type '[String: Any?]'

我不知道如何修复该错误,也没有通过扩展或 map() 成功实现预期结果,但我有另一种解决问题的方法,使用 函数:

正在声明字典:

var date = NSDate()
var swiftDict:[String : Any?] = ["1":  date, "2": "two", "3": 15, "4": true]

函数:

func firebaseFriendlyDictionary(_ dict: [String : Any?]) -> [String : Any?]{
    var Dict = dict
    for (key, value) in dict
    {
        if (value is NSDate){
            Dict[key] = (value as! NSDate).timeIntervalSince1970
        }
    }
    return Dict
}

用法:

swiftDict = firebaseFriendlyDictionary(swiftDict)

测试:

假设我们有日期 2017-02-04 16:42:46 +0000,输出是 1486226566.2349629,这是正确的。

为什么不映射词典? 正如 Losiowaty 在他的出色回答中指出的那样,map 总是 returns 一个 Array,在本例中是一个 Array of Tuples([T])。在我看来,在此上下文中不需要 map 函数,而且它需要更多代码才能完成。

希望对您有所帮助!

您的问题在于,map 总是 return 是 Array,即使应用于 Dictionary。您的错误消息基本上意味着,您将方法声明为 returning a Dicitonary,但是 returns 中的语句是 Array[T] - 表示包含 some 类型 T) 对象的数组。在您的情况下,由 map 编辑的数组 return 将包含 元组 (更多关于它们 here)。在这种情况下,它看起来像一个键值对,但它不等同于字典中的 key-value 对。基本上,元组使您能够从方法中 return 多个 value/object。您可以将它们视为 匿名 结构。

在我看来,没有必要使用 map 来完成你需要的 - Xcoder 先生提供的解决方案是可行的方法。

如果你真的想使用像 map 这样的功能,你真正想要的方法是 reduce.

我来演示一下。为了让事情尽可能清楚,我认为如果我们将您的价值观所经历的转变分离成它自己的一个功能,那将会有所帮助:

func dateToSeconds(_ thing:Any?) -> Any? {
    guard let date = thing as? Date else {return thing}
    return date.timeIntervalSince1970
}

好的,这是我们的测试词典:

let d1 : [String:Any?] = ["1":Date(), "2":"two", "3":15, "4":true]

现在我们可以申请了reduce。它将两个参数传递给它的函数。第一个是 "accumulator" 我们不断建立最终结果的地方,在本例中是另一个字典。第二个是原始字典的一个元素,表示为 元组 的 key-value 对,称为 keyvalue:

let d2 = d1.reduce([String:Any?]()) { (dict, tuple) in
    var dict = dict
    dict[tuple.key] = dateToSeconds(tuple.value)
    return dict
}

当我们检查 d2 时,我们发现我们得到了正确的答案:

d2 // ["3": {some 15}, "2": {some "two"}, "1": {some 1486228695.557882}, "4": {some true}]