【问题标题】:Array.map() produces '[T]', not the expected contextual result type '[String: Any?]'Array.map() 产生'[T]',而不是预期的上下文结果类型'[String: Any?]'
【发布时间】:2017-06-21 15:31:45
【问题描述】:

我正在编写一个扩展来桥接 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?]'

【问题讨论】:

  • @Xcoder123 我认为我的问题更多与我对 Swift 的Array.map() 的理解有关,而不是 Eureka 本身
  • This 帮助了我。

标签: ios swift firebase firebase-realtime-database eureka-forms


【解决方案1】:

您的问题在于map 始终返回Array,即使应用于Dictionary 也是如此。您的错误消息基本上意味着您声明您的方法返回一个Dicitonary,但里面的语句返回一个Array[T] - 表示一个带有一些类型T的对象的数组)。在您的情况下,map 返回的数组将包含 元组(更多关于它们的信息 here)。在这种情况下,它看起来像一个键值对,但它不等同于字典中的键值对。基本上,元组使您能够从方法中返回多个值/对象。您可以将它们视为 匿名 结构。

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

【讨论】:

  • 为了解释清楚而标记为正确答案。简而言之:元组数组≠字典...[(String, Any?)] ≠ [String: Any?]。谢谢!
【解决方案2】:

如果你真的想使用像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。它将两个参数传递给它的函数。第一个是我们不断建立最终结果的“累加器”,在这种情况下是另一个字典。第二个是原始字典的元素,表示为 tuple 键值对,称为 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}]

【讨论】:

  • 减少似乎是要走的路。我将Losiowaty's answer 标记为答案,因为它解释了错误。谢谢!
  • 我不知道你在做什么,但我向你展示的内容确实有效。请注意,在我的reduce 函数的第一行中,我将dict 分配给var;这就是你在说的吗?这条线很关键。 (嗯,这一切都很关键;它们都挂在一起。)
  • 哦,是的,就是这样。我不知道这很重要,我在文档中没有看到。再次感谢!
【解决方案3】:

我不知道如何修复该错误,也无法通过扩展名或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 总是返回一个 Array,在这个以Tuples([T]) 的Array 为例。在我看来,在这种情况下不需要地图功能,而且它需要更多的代码来完成。

希望这会有所帮助!

【讨论】:

  • 我已经提交了一个带有错误解释的答案。我将发布相同的方法来完成 OP 用例;)
  • 是的,我会按照你的方式做。
  • 我更愿意以实用的方式完成它。减少似乎是要走的路。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-07
  • 1970-01-01
  • 2019-04-08
  • 1970-01-01
相关资源
最近更新 更多