在Swift中修改字典数组

时间:2014-09-22 16:40:58

标签: arrays dictionary swift

我是Swift的新手,并且在查找数组和字典的某些方面时遇到了一些麻烦。

我有一系列词典,我使用过类型别名 - 例如

typealias myDicts = Dictionary<String, Double>

var myArray : [myDicts] = [
["id":0,
    "lat”:55.555555,
    "lng”:-55.555555,
    "distance":0],
["id":1,
    "lat": 44.444444,
    "lng”:-44.444444,
    "distance":0]
]

然后,我想迭代数组中的字典并更改“距离”键值。我是这样做的:

for dict:myDicts in myArray {

dict["distance"] = 5

}

或者甚至特别确保5是双重的,有许多不同的方法,包括例如

for dict:myDicts in myArray {

let numberFive : Double = 5

dict["distance"] = numberFive

}

我的所有尝试都会导致错误:

 @lvalue $T5' is not identical to '(String, Double)

似乎表现为里面的字典是不可变的“让”而不是“var”。所以我随机尝试了这个:

for (var dict:myDicts) in myArray {

dict["distance"] = 5

}

这消除了错误,并且在for循环中确实为key分配了5,但是从长远来看,这似乎并没有实际修改数组本身。我做错了什么?

4 个答案:

答案 0 :(得分:5)

默认情况下,Swift中for-in循环中隐式声明的变量是常量(let),这就是为什么你不能在循环中直接修改它的原因。

for-in documentation有这个:

for index in 1...5 {
    println("\(index) times 5 is \(index * 5)")
}
  

在上面的示例中,index是一个常量,其值是自动的   在循环的每次迭代开始时设置。因此,它没有   必须在使用之前申报。它是隐含声明的   只需将其包含在循环声明中,无需使用   一个let声明关键字。

正如您所发现的那样,您可以通过使用var明确声明它来使其成为变量。但是,在这种情况下,您尝试修改作为结构的字典,因此修改value type并在分配时复制它。当您执行dict["distance"] = 5时,您实际上正在修改字典的副本而不是存储在数组中的原始副本。

您仍然可以修改数组中的字典,只需通过索引循环遍历数组即可直接执行:

for index in 0..<myArray.count {
    myArray[index]["distance"] = 5
}

通过这种方式,您可以通过修改原始字典而不是副本来进行修改。

话虽如此,@ matt建议使用自定义课程通常是最佳选择。

答案 1 :(得分:2)

你没有做错任何事。这就是Swift的工作方式。您有两种选择:

  • 使用NSMutableDictionary而不是Swift词典。

  • 使用自定义类而不是字典。在某种程度上,这是一个更好的解决方案,因为在所有词典具有相同结构的情况下,这是你应该一直在做的事情。

我所说的“自定义类”仅仅是一个“价值类”,一组属性。这在Objective-C中是一种痛苦,但在Swift中它是微不足道的,所以我现在做了很多。问题是你可以在任何地方坚持自定义类的类定义;它不需要自己的文件,当然在Swift中你没有接口/实现foo来解决,更不用说内存管理和其他东西了。所以这只是几行代码,你可以使用你已经拥有的代码。

以下是我自己的代码中的示例:

class Model {
    var task : NSURLSessionTask!
    var im : UIImage!
    var text : String!
    var picurl : String!
}

然后我们有一个模型数组,然后我们去。

所以,在你的例子中:

class MyDict : NSObject {
    var id = 0.0
    var lat = 0.0
    var lng = 0.0
    var distance = 0.0
}

var myArray = [MyDict]()

let d1 = MyDict()
d1.id = 0
d1.lat = 55.55
d1.lng = -55.55
d1.distance = 0
let d2 = MyDict()
d2.id = 0
d2.lat = 44.44
d2.lng = -44.44
d2.distance = 0
myArray = [d1,d2]

// now we come to the actual heart of the matter

for d in myArray {
    d.distance = 5
}
println(myArray[0].distance) // it worked
println(myArray[1].distance) // it worked

答案 2 :(得分:0)

是的,在循环中检索的字典是不可变的,因此您无法更改。 我担心你的最后一次尝试只是创造了一个可变的副本。

一种可能的解决方法是使用NSMutableDictionary

typealias myDicts = NSMutableDictionary

答案 3 :(得分:0)

拥有Swift词典或数组的类包装器。

class MyDictionary: NSObject {
var data : Dictionary<String,Any>!
init(_ data: Dictionary<String,Any>) {
    self.data = data
}}

MyDictionary.data