簡體   English   中英

如何在Swift中為Dictionary添加引用

[英]How to assign a reference to a Dictionary in Swift

我正在使用復雜的字典,並希望只需為其分配變量即可輕松完成工作。

myDictionay["with"]["complex"]["sub"]["dictionary"] = "NewValue"

我只想要這個:

let smaller = myDictionay["with"]["complex"]["sub"]
smaller["dictionary"] = "NewValue"

我該怎么做?

Swift Dictionary (和Array / Set )遵循傳遞引用語義,而不是通過值語義傳遞(如果你查看頭文件,你會看到它是一個struct ,而不是一個class )。 這意味着當您將Dictionary實例從一個變量分配給另一個變量,並更改與該新變量關聯的值時,它實際上不會更改與原始值關聯的值。 因此,使用Swift Dictionary無法實現您正在尋找的語法。 話雖如此,您總是可以使用NSMutableDictionary ,然后您希望的語法將起作用。

您可以使用閉包為您執行內部訪問:

let smaller : (inout _: [String : [String : [String :[String : String]]]], key: String, val: String) -> () = { dict, key, val in
    dict["with"]?["complex"]?["sub"]?[key] = val
    return ()
}

/* setup example */
var a = [String : String]()
var b = [String :[String : String]]()
var c = [String : [String : [String : String]]]()
var myDictionary = [String : [String : [String :[String : String]]]]()

a["dictionary"] = "OldValue"
b["sub"] = a
b["anothersub"] = a
c["complex"] = b
myDictionary["with"] = c

/* example */
print(myDictionary)
/* ["with": ["complex": ["anothersub": ["dictionary": "OldValue"],
    "sub": ["dictionary": "OldValue"]]]] */

smaller(&myDictionary, key: "dictionary", val: "NewValue")
print(myDictionary)
/* ["with": ["complex": ["anothersub": ["dictionary": "OldValue"],
    "sub": ["dictionary": "NewValue"]]]] */

或者,更精簡:你可以使用一個閉包,特別是在使用閉包的范圍內可以訪問的字典名稱(即,不需要發送對字典的引用作為閉包的參數)。

let smaller2 : (String, String) -> () = { myDictionary["with"]?["complex"]?["sub"]?[$0] = $1 }
smaller2("dictionary", "NewerValue")
print(myDictionary)
/* ["with": ["complex": ["anothersub": ["dictionary": "OldValue"],
    "sub": ["dictionary": "NewerValue"]]]] */

如果你將你的字典myDictionary作為一個類屬性處理,你可以作為上面的替代,定義一個類方法,返回上面的閉包,給定一個“字典鍵路徑”,例如"with.complex.sub" ,作為論點:

/* say 'myDictionary' is some class property (initialized as in example above)
   In same class, introduce the following method */
func dictClosure(dictKeyPath: String) -> ((String, String) -> ()) {
    let arr = dictKeyPath.componentsSeparatedByString(".")
    if arr.count == 3 {
        return {
            myDictionary[arr[0]]?[arr[1]]?[arr[2]]?[$0] = $1 }
    }
    else {
        return {
            _, _ in
            print("This closure is invalid")
        }
    }
}

/* example usage */
var smaller3 = dictClosure("with.complex.sub")
smaller3("dictionary", "NewestValue")
smaller3 = dictClosure("with.complex.anothersub")
smaller3("dictionary", "AlsoNewValue")
print(myDictionary)
/* ["with": ["complex": ["anothersub": ["dictionary": "AlsoNewValue"], 
    "sub": ["dictionary": "NewestValue"]]]] */

上面假設三個級別的字典鍵路徑( "one.two.three" ),並產生用於訪問第四級字典的閉包。


最后請注意,對於上述所有解決方案,調用smaller閉包將允許新的鍵值對添加到字典的第四級,而不僅是改變現有對的值。 例如,關鍵字錯誤smaller3("dcitionary", "NewValue")將在第四級字典中添加鍵值對"dcitionary": "NewValue" 如果您只想允許現有密鑰的變異值,只需添加? 在上面smaller閉包中最內部的密鑰訪問之后:

/* smaller ... */
dict["with"]?["complex"]?["sub"]?[key]? = val

/* smaller2 ... */
myDictionary["with"]?["complex"]?["sub"]?[$0]? = $1

/* smaller3 ... */
myDictionary[arr[0]]?[arr[1]]?[arr[2]]?[$0]? = $1

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM