【问题标题】:Merge dictionary in swift with unique keys使用唯一键快速合并字典
【发布时间】:2018-11-03 12:36:28
【问题描述】:

我正在尝试对具有唯一类型的字典求和-

   let dict1: [String:Any] = ["type":"steps","value": 100]
   let dict2: [String:Any] = ["type":"cal","value": 200]
   let dict3: [String:Any] = ["type":"cal","value": 300]
   let dict4 : [String:Any] = ["type":"steps","value": 400]
   let dict5 : [String:Any] = ["type":"cal","value": 500]

我只是在寻找结果-

sum is - [["type":"steps","value": 500],["type":"cal","value": 1000]]

我通过https://developer.apple.com/documentation/swift/dictionary 但没有找到我需要的东西

请帮忙

【问题讨论】:

标签: ios swift dictionary swift4


【解决方案1】:
func sumDict(arrayOfDict: [[String:Any]]) -> [[String:Any]] {
    var stepVal = 0, calVal = 0
    for dict in arrayOfDict {
        if let typeValue = dict["type"] as? String, typeValue == "steps" {
            if let val = dict["value"] as? Int {
                stepVal += val
            }
        } else if let typeValue = dict["type"] as? String, typeValue == "cal" {
            if let val = dict["value"] as? Int {
                calVal += val
            }
        }
    }

    let resultDic = [["type":"cal","value": calVal],["type":"steps","value": stepVal]]
    return resultDic
}
let dict1: [String:Any] = ["type":"steps","value": 100]
let dict2: [String:Any] = ["type":"cal","value": 200]
let dict3: [String:Any] = ["type":"cal","value": 300]
let dict4: [String:Any] = ["type":"steps","value": 400]
let dict5: [String:Any] = ["type":"cal","value": 500]

let array = [dict1,dict2,dict3,dict4,dict5]

print("sum is - \(sumDict(arrayOfDict: array))")

【讨论】:

    【解决方案2】:

    你可以这样做:

            let dict1: [String:Any] = ["type":"steps","value": 100]
            let dict2: [String:Any] = ["type":"cal","value": 200]
            let dict3: [String:Any] = ["type":"cal","value": 300]
            let dict4 : [String:Any] = ["type":"steps","value": 400]
            let dict5 : [String:Any] = ["type":"cal","value": 500]
    
            let array = [dict1,dict2,dict3,dict4,dict5]
    
            let list :[String:[[String:Any]]] = Dictionary(grouping: array, by: {$0["type"] as? String ?? ""})
    
            let result =  list.map { (key,value) -> [String:Any] in
                let sum = value.reduce(0, {$0 + ($1["value"] as? Int ?? 0)})
                return ["type":key , "value":sum]
            }
    
            print(result)
    

    输出:

    [["type": "cal", "value": 1000], ["type": "steps", "value": 500]]
    

    【讨论】:

    • 您的解决方案完美运行。 但是看起来[String:[[String:Any]]]可能有性能问题。
    • 如果任何字典不包含“类型”键,这将崩溃。否则很好的解决方案。
    • 根据他在 Question 中写的数据回答,
    【解决方案3】:

    如果您的字典始终包含具有相同类型值的相同键,则将它们转换为对象是有意义的。它使求和更容易。

    let dict1: [String: Any] = ["type":"steps","value": 100]
    let dict2: [String: Any] = ["type":"cal","value": 200]
    let dict3: [String: Any] = ["type":"cal","value": 300]
    let dict4: [String: Any] = ["type":"steps","value": 400]
    let dict5: [String: Any] = ["type":"cal","value": 500]
    
    let dicts = [dict1, dict2, dict3, dict4, dict5]
    
    // wrapper class
    
    class Wrapper {
    
        // keys
        static let typeKey = "type"
        static let valueKey = "value"
    
        // values
        var type: String
        var value: Int
    
        // init
        init?(dict: [String: Any]) {
            guard let type = dict[Wrapper.typeKey] as? String, let value = dict[Wrapper.valueKey] as? Int else {
                // dict has to contain value & type keys to be valid
                return nil
            }
    
            self.type = type
            self.value = value
        }
    
        // converting back to dictionary
        func toDict() -> [String: Any] {
            return [Wrapper.typeKey: type, Wrapper.valueKey: value]
        }
    
        // summing
        static func sumWrappers(_ wrappers: [Wrapper]) -> [Wrapper] {
            var result: [Wrapper] = []
            wrappers.forEach { wrapper in
                if let existing = result.first(where: { $0.type == wrapper.type }) {
                    // wrapper of this type already exists -> increase the value
                    existing.value += wrapper.value
                } else {
                    // new type of wrapper -> just add it to the result
                    result.append(wrapper)
                }
            }
    
            return result
         }
    }
    
    // usage
    
    let wrappers = dicts.compactMap { Wrapper(dict: $0) } // get valid wrappers
    let result = Wrapper.sumWrappers(wrappers) // get sums for all the different types
    
    let resultArray = result.map { $0.toDict() } // contains the final result as array of dictionaries
    

    结果

    [["type": "steps", "value": 500], ["type": "cal", "value": 1000]]

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-23
      • 2018-07-26
      • 2020-12-21
      • 1970-01-01
      • 2016-11-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多