'(key: String, value: Any)' 无法转换为 '[String : Any]'。

3

我正在尝试重构以下代码:

var indices = [String:[Int:Double]]()
apps.forEach { app in indices[app] = [Int:Double]()}
    
var index = 0
timeSeries.forEach { entry in
    entry.apps.forEach{ (arg: (key: String, value: Double)) in
        let (app, value) = arg
        indices[app]?[index] = value
    }
        
    index += 1
}

我有这样的签名:

var parameters = timeSeries.map{ entry in entry.apps as [String:Any] }
var indices = getIndices(with: apps, in: parameters) as? [String:[Int:Double]] ?? [String:[Int:Double]]()

而这个方法:
func getIndices(with source: [String], in entryParameters: [[String:Any]]) -> [String:[Int:Any]] {
    var indices = [String:[Int:Any]]()
    source.forEach { item in indices[item] = [Int:Any]() }
    
    var index = 0
    entryParameters.forEach { (arg: (key: String, value: Any)) in
        let (key, value) = arg
        indices[key]?[index] = value
        
        index += 1
    }

    return indices
}

但是这样做(只在方法中,原始内容没有问题)会出现:entryParameters行显示'(key: String, value: Any)'不可转换为'[String : Any]'

我必须使用Any的原因是另一个来源是[String:[Int:Bool]]

编辑:更多细节:

timeSeries是[TimeSeriesEntry]

// this will need to be defined per-model, so in a different file in final project
struct TimeSeriesEntry: Codable, Equatable {
    let id: String
    let uid: String
    let date: Date
    let apps: [String:Double]
    let locations: [String:Bool]
    
    func changeApp(app: String, value: Double) -> TimeSeriesEntry {
        var apps = self.apps
        apps[app] = value
        
        return TimeSeriesEntry(id: self.id, uid: self.uid, date: self.date, apps: apps, locations: self.locations)
    }
}

注释:

更改了调用签名,感谢impression。问题仍然存在。


2
应该是[String:Any]而不是[[String:Any]]吧? - impression7vx
如果我这样做,那么我的调用行(分配给索引)将在timeSeries.map处出现Cannot convert value of type '[[String : Double]]' to expected argument type '[String : Any]'错误-- 我添加了timeSeries结构的详细信息以增加清晰度。 - roberto tomás
那是因为你正在执行 timeSeries.map{ entry in entry.apps }) as? [String:[Int:Double]] ?? [String:[Int:Double]]()。所以,我猜这取决于你想要什么。在两种情况下,似乎都需要将其类型转换为 [String:[Int:Double]][String:[Int:Double]]()。现在,你说你也需要它用于 bool。然而,如果是这样的话,当你将其带入参数时,你需要将你的 [String:[Int:Double]] 转换为 [String:Any],当它作为参数进入函数时。 - impression7vx
我建议尝试使用timeSeries.map{ entry in entry.apps }) as? [String:Any] ?? [String:[Int:Double]](),因为如果[String:Any]返回nil,那么你就知道需要一个新的,即[String:[Int:Double]] - impression7vx
不要在参数上进行强制转换,而是在返回值上进行。仔细看,该参数是 TimeSeriesEntry.app [String:Double] 的数组。强制转换是 [String:[Int:Double]],同样是在返回值上进行的(我想赋值中左侧的类型说明不需要,但右侧需要)。[String:Double] 应该能够优雅地向下转换为 [String:Any],而不需要强制转换,对吗? - roberto tomás
只是为了确保,我改变了调用签名,感谢印象。但问题仍然存在。 - roberto tomás
2个回答

1
问题在于,entryParameters 中的每个值都是一个字典,因此当您执行 entryParameters.forEach 时,在闭包中得到的是字典类型而不是 (key, value)
当您在此字典上调用 forEach 时,将获得 (key,value)。因此,您的方法应该类似于这样:
func getIndices(with source: [String], in entryParameters: [[String:Any]]) -> [String:[Int:Any]] {
    var indices = [String:[Int:Any]]()
    source.forEach { item in indices[item] = [Int:Any]() }

    var index = 0
    entryParameters.forEach { entry in
        entry.forEach {(arg: (key: String, value: Any)) in
            let (key, value) = arg
            indices[key]?[index] = value
        }

        index += 1
    }

    return indices
}

0

我在 Playground 中简单测试了一下。

var double = [String:[Int:Double]]()
double["Taco"] = [2: 3.2]

func myFunc(double: [String:[Int:Double]]) {
    print(double.count) //Prints 1
    print(double["Taco"]!) //Prints [2:3.2]
}

func myFunc2(all: [String:Any]) {
    print(all.count) //Prints 1
    print(all["Taco"]!) //Prints [2:3.2]
}


myFunc(double: double)
myFunc2(all: double as [String:Any])

我有一个初始的[String:[Int:Double]]()。在这个字典中,我设置了double["Taco"] = [2: 3.2]。我可以使用两个不同的函数,一个是以原始类型[String:[Int:Double]]作为参数类型,使用起来很容易。然而,现在我创建了一个函数,它接受一个[String:Any]类型的字典。现在,为了使用这个方法,我们必须在调用方法时将变量强制转换为[String:Any],如下所示。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接