在Swift中轻松访问和修改字典数组

时间:2017-01-10 02:38:21

标签: arrays swift dictionary

我有这样的结构:[String: [String: Double]]()

具体来说,类似于:var dictionaries = ["GF": ["ET": 4.62, "EO": 21.0],"FD": ["EE": 80.95, "DE": 0.4]]

如何轻松访问和修改嵌套词典?

更新示例:我想在"TT": 6附加FD,之后我想在数组中添加另一个字典。最后我会打印结果。

for (key,value) in dictionaries {

    // if array contains FD, add the record to FD
    if key.contains("FD") {
        dictionaries["FD"]!["TT"] = 6
    }
    else {
    // if array doesn't contain FD, add FD and add the record to it
        dictionaries = dictionaries+["FD"]["TT"] = 6 // <-- I know that it's wrong but I want to achieve this result in this case.
    }
}

打印结果将是:

GF -> ET - 4.62, EO - 21.0
FD -> EE - 80.95, DE - 0.4, TT - 6

使命:我需要添加上面示例中的新字典记录,以简单直接的方式更新现有字典记录,轻松遍历记录以读取值并打印出来。

任何人都可以帮助我吗?从那时起就没有机会在Swift中管理词典。

2 个答案:

答案 0 :(得分:0)

如果您拥有>"known\%i2.txt&#34; FD&#34;它会更简单。你可以用

key

添加新值[&#34; TT&#34;:6]或将TT的现有值修改为6.注意!在[&#34; FD&#34;]之间![&#34; TT&#34;]假定[&#34; FD&#34;]无论如何都存在。您需要检查是否存在[&#34; FD&#34;]。像:

dictionaries["FD"]!["TT"] = 6

如果您需要查找if dictionaries["FD"] != nil { dictionaries["FD"]!["TT"] = 6 } else { dictionaries["FD"] = ["TT" : 6] } ,则必须按照您已经尝试过的方式运行整个字典,但字典支持快速枚举键和值,例如

key

答案 1 :(得分:0)

目前尚不清楚你究竟需要什么,但练习让我很开心,所以我came up使用这个解决方案:我们扩展Dictionary以便它提供方便的方法,如果它是一个嵌套字典。

首先,由于Swift的特性,我们必须创建一个虚拟协议来“标记”Dictionary¹:

protocol DictionaryProtocol {
    associatedtype Key: Hashable
    associatedtype Value

    subscript(key: Key) -> Value? { get set }
    var keys: LazyMapCollection<[Key : Value], Key> { get }
}

extension Dictionary: DictionaryProtocol {}

基本上,只需将以后需要的所有声明从Dictionary复制粘贴到DictionaryProtocol

然后,你可以愉快地延伸。例如,添加一个双参数下标:

extension Dictionary where Value: DictionaryProtocol {
    typealias K1 = Key
    typealias K2 = Value.Key
    typealias V  = Value.Value

    subscript(k1: K1, k2: K2) -> V? {
        get {
            return self[k1]?[k2]
        }
        set {
            if self[k1] == nil {
                self.updateValue([K2: V]() as! Value, forKey: k1)
            }

            self[k1]![k2] = newValue
        }
    }
}

或另一种漂亮的印刷品:

extension Dictionary where Value: DictionaryProtocol {
    func pretty() -> String {
        return self.keys.map { k1 in
            let row = self[k1]!.keys.map { k2 in
                return "\(k2) - \(self[k1]![k2]!)"
            }.joined(separator: ", ")

            return "\(k1) -> \(row)"
        }.joined(separator: "\n")
    }
}

您还可以为此特殊字典创建类型别名:

typealias D2Dictionary<K: Hashable, V> = Dictionary<K, Dictionary<K, V>>

回到你问题中的例子:

var dictionary = D2Dictionary<String, Double>()
dictionary["GF", "ET"] = 4.62
dictionary["GF", "EO"] = 21.0
dictionary["FD", "EE"] = 80.95
dictionary["FD", "DE"] = 0.4
dictionary["FD", "TT"] = 6

print(dictionary.pretty())

// > GF -> ET - 4.62, EO - 21.0
// > FD -> EE - 80.95, DE - 0.4, TT - 6.0
  1. 背景:在扩展条件下,只能在类型边界中使用协议。
  2. 确保获得正确的类型。如果我们编写var keys: [Key] { get },例如编译器dies with a seg fault
  3. 不幸的是,无论出于何种原因,都不允许extension Dictionary: CustomStringConvertible where Value: DictionaryProtocol { ... }