我对Swift有一个非常简单的问题。 我创建了这个函数:
var dictAges : [String: Int] = ["John":40, "Michael":20, "Bob": -16]
func correctAges(dict:[String:Int]) {
for (name, age) in dict {
guard age >= 0 else {
dict[name] = 0
continue
}
}
}
correctAges(dict:dictAges)
但我不明白错误:
“不能通过下标分配:'dict'是'let'常量,dict [name] = 0”
我该如何解决?
答案 0 :(得分:10)
函数的输入参数在函数体内是不可变的,而Dictionary是值类型,因此您在函数内看到的dict
实际上是原始dictAges
的副本。当您使用值类型作为其输入参数调用函数时,该输入参数将按值传递,而不是通过引用传递,因此在函数内部您无法访问原始变量。
将dict
输入参数声明为inout,或者如果您更喜欢功能更强大的方法,则从函数中返回字典的变异版本。
功能方法:
var dictAges : [String: Int] = ["John":40, "Michael":20, "Bob": -16]
func correctAges(dict:[String:Int])->[String:Int] {
var mutatedDict = dict
for (name, age) in mutatedDict {
guard age >= 0 else {
mutatedDict[name] = 0
continue
}
}
return mutatedDict
}
let newDict = correctAges(dict:dictAges) //["Michael": 20, "Bob": 0, "John": 40]
Inout版本:
func correctAges(dict: inout [String:Int]){
for (name,age) in dict {
guard age >= 0 else {
dict[name] = 0
continue
}
}
}
correctAges(dict: &dictAges) //["Michael": 20, "Bob": 0, "John": 40]
答案 1 :(得分:0)
您希望改变传入函数的字典是错误的,原因很简单,Swift中的字典是值类型。字典中的类型String和Int也是值。这意味着,实际上,参数dict
是原始dictAges
的副本。您对dict
所做的任何操作都不会对dictAges
产生任何影响。
这表明您应该重新考虑整个架构。如果输入负数作为年龄是错误的,那么您应该在输入时预先记录下来。实际上,你在这里使用Int字典作为模型的整个过程可能是不正确的。你应该使用Person的字典,其中Person是一个带有age
的结构体和一个阻止age
首先出现负面的setter。
如果必须有一个贯穿任意字典的函数并将值修复为非负数,那么将其作为字典的一个特性:
var dictAges : [String: Int] = ["John":40, "Michael":20, "Bob": -16]
extension Dictionary where Value : SignedInteger {
mutating func fixAges() {
for (k,v) in self {
if v < 0 {
self[k] = 0
}
}
}
}
dictAges.fixAges()
答案 2 :(得分:0)
一般来说,在循环遍历序列时改变序列是不好的,这就是为什么你只在代码中获得字典的不可变副本。
Swift 4
我认为更好的方法可能是使用map
,并采用更实用的方法:
var dictAges : [String: Int] = ["John":40, "Michael":20, "Bob": -16]
func correctAges(dict:[String:Int]) -> [String:Int]
{
let corrected = dict.map { (name, age) in age > 0 ? (name, age) : (name, 0) }
return Dictionary(uniqueKeysWithValues: corrected)
}
dictAges = correctAges(dict: dictAges)
print(dictAges) // ["Michael": 20, "Bob": 0, "John": 40]
这样您就可以将此方法重用于任何[String:Int]
字典。