【问题标题】:Iterate through Dictionary over all levels遍历所有级别的字典
【发布时间】:2021-05-20 15:45:36
【问题描述】:

我在字典中有一个数据结构,如下所示:

- device
   - type
   - isActive
   - Data
      - Manufacturer 
      - Build Date
      - Power
      ...
   - Example

现在,如果我创建一个 For 循环,它只会显示第一级的值,这意味着

type, isActive, Data, Example


for (key, value) in value {

}

以下所有数据(例如构建日期或电源)都丢失了 - 我怎么也能通过这些级别感到恼火?

【问题讨论】:

标签: ios swift loops dictionary


【解决方案1】:

假设您有类型为 [String:Any] 的字典,将其展平的函数将类似于:

    func flatten(_ obj:[String:Any]) -> [String:Any] {
        var result = [String:Any]()
        for (key, val) in obj {
            if let v = val as? [String:Any] {
                result = result.merging(flatten(v), uniquingKeysWith: {
                    $1
                })
            }
            //I also included initial value of internal dictionary
            /if you don't need initial value put next line in 'else'
            result[key] = val 
        }
        return result
    }

要使用它:

    let d:[String:Any] = [
        "test1":1,
        "test2":2,
        "test3":[
            "test3.1":31,
            "test3.2":32
        ]
    ]
    let res = flatten(d)
    print(res)

[“test2”:2,“test3.2”:32,“test3.1”:31,“test1”:1,“test3”: [“test3.2”:32,“test3.1”:31]]

注意:字典不是排序结构

【讨论】:

  • 谢谢!这正是我想要的!晚上过得愉快!
【解决方案2】:

您正在处理Recursion 问题。


你可以逐级字典:

func walk(dictionary: [String: Any]) {
    for (key, value) in dictionary {
        print("\(key): \(value)")
        if let value = value as? [String: Any] {
            walk(dictionary: value)
        }
    }
}

您可以将[String: Any] 类型更改为您的字典类型(NSDictionary 等)

【讨论】:

    【解决方案3】:

    正如 Tomas 所说,这可以通过递归来解决。他的“walk”函数只是在不同的行上打印值,但没有键,也没有格式化。这是使用您概述的结构记录嵌套字典的代码:

    //Define the keys we use in our example
    enum keys: String {
        case device
        case type
        case isActive
        case Data
        case Manufacturer
        case BuildDate
        case Power
        case Example
        }
    
    //Create a sample dictionary using those keys and some random values
    let dict = [keys.device.rawValue:
                    [keys.type.rawValue: "appliance",
                     keys.isActive.rawValue: true,
                     keys.Data.rawValue:
                        [keys.Manufacturer.rawValue: "GE",
                         keys.BuildDate.rawValue: "12/23/96",
                         keys.Power.rawValue: 23,
                        ],
                     keys.Example.rawValue: "Foo"
                    ]
    ]
    
    //Create an extension of Dictionary for dictionaries with String Keys.
    extension Dictionary where Key == String {
        
        //Define a function to recursively build a description of our dictionary
        private func descriptionOfDict(_ aDict: [String: Any], level: Int = 0) -> String {
            var output = ""
            var indent: String = ""
            if level > 0 {
                output += "\n"
                for _ in 1...level {
                    indent += "   "
                }
            }
            for (key,value) in aDict {
                output += indent + key + ": "
                if let subDict = value as? [String: Any] {
                    //If the value for this key is another dictionary, log that recursively
                    output +=  descriptionOfDict(subDict, level: level+1)
                } else {
                    if let aString = value as? String {
                        output += "\"" +  aString + "\"\n"
                    }  else {
                        output += String(describing: value) + "\n"
                    }
                }
            }
            return output
        }
        
        //Add a description property for dictionaries
        var description: String  {
            return descriptionOfDict(self)
        }
    }
    
    
    print(dict.description)
    

    输出:

    device: 
       isActive: true
       Data: 
          Manufacturer: "GE"
          Power: 23
          BuildDate: "12/23/96"
       Example: "Foo"
       type: "appliance"
    

    编辑:

    上面定义了String 属性description,当您打印[String:Any] 字典时会更改输出。如果您不希望这样,请将属性 description 重命名为 dictDescription 之类的其他名称

    【讨论】:

    • 我认为将其命名为描述不是一个好主意。原始描述属性将无法访问。
    • 我打算覆盖 description 属性。如果您不想更改默认描述输出,请务必将其称为其他名称。我为此添加了评论。 (我一直在我的自定义类和结构中添加customStringConvertible 一致性和description 属性。这是一个非常方便的调试辅助工具。)
    猜你喜欢
    • 2015-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-24
    相关资源
    最近更新 更多