如何在Swift中为Dictionary添加引用

时间:2016-01-23 00:12:36

标签: swift dictionary

我正在使用复杂的字典,并希望只需为其分配变量即可轻松完成工作。

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

我只想要这个:

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

我该怎么做?

2 个答案:

答案 0 :(得分:3)

Swift Dictionary(和Array / Set)遵循传递引用语义,而不是传递值语义(如果你查看标题,你会看到它是struct,而不是class)。这意味着当您将Dictionary实例从一个变量分配给另一个变量,并更改与新变量关联的值时,实际上会更改与原始值关联的值。因此,使用Swift Dictionary无法实现您正在寻找的语法。话虽如此,您总是可以使用NSMutableDictionary代替,然后您希望的语法将起作用。

答案 1 :(得分:1)

您可以使用闭包为您执行内部访问:

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