2014-09-22 71 views
3

我是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) 

這似乎是充當如果字典裏是不可改變的「讓」,而不是「變種」。所以,筆者隨機嘗試這樣做:

for (var dict:myDicts) in myArray { 

dict["distance"] = 5 

} 

這消除了錯誤,關鍵確實是分配5中的for循環,但這似乎並沒有實際修改陣列本身的長遠之計。我究竟做錯了什麼?

回答

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 
+0

謝謝 - 使用自定義類似乎是一個好主意。但是我在項目中遇到了一些麻煩......你能舉個例子說明在我的問題中這個例子可以如何工作嗎? – Dana 2014-09-22 18:13:54

+2

當然,但這很容易,很明顯;我不應該爲你寫代碼。 – matt 2014-09-22 19:23:03

+0

對不起,我只是需要更多的澄清。這並不是說我需要專門爲我的代碼提供一個示例,但在完整的環境中看到整個行動真的有助於那些新手。我現在知道了! – Dana 2014-09-22 19:50:03

0

是的,在循環中檢索到的字典是不可改變的,因此你不能改變。我恐怕你最後一次嘗試只是創建一個可變的副本。

一個可能的解決方法是使用NSMutableDictionary

typealias myDicts = NSMutableDictionary 
5

中隱式聲明的變量爲,在斯威夫特循環是默認(let)不變,這就是爲什麼你不能直接修改循環。

for-in documentation有這樣的:

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

In the example above, index is a constant whose value is automatically set at the start of each iteration of the loop. As such, it does not have to be declared before it is used. It is implicitly declared simply by its inclusion in the loop declaration, without the need for a let declaration keyword.

正如你已經發現,你可以通過var明確聲明它使它成爲一個變量。但是,在這種情況下,您正在嘗試修改一個結構體的字典,因此它是一個value type,它在賦值時被複制。當你做dict["distance"] = 5你實際上修改了字典的副本,而不是存儲在數組中的原始數據。

您仍然可以修改字典數組中,你只需要直接由指數循環數組超過做到這一點:

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

這樣,你通過修改原有的字典,而不是一定能它的副本。

這就是說,@亞特的建議使用自定義類通常是最好的路線。

0

有一個Swift字典或數組的類包裝。

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

MyDictionary.data