无法通过下标分配:'dict'是'let'常量

时间:2017-11-15 15:11:00

标签: swift

我对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”

我该如何解决?

3 个答案:

答案 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]字典。