【问题标题】:Remove duplicates in dictionary and leave only min values删除字典中的重复项并仅保留最小值
【发布时间】:2019-06-05 16:42:39
【问题描述】:

我有[Int:[String:String]] 类型的字典

例子:

[1546696330:[“符号”:“ETH”,“数量”:“1.0”],1546531017:[“符号”:“ETH”,“数量”:“1.0”],1546531031:[“符号” :“XRP”,“金额”:“200.0”]]

如您所见,我有 2 个重复的字典,键为 symbol,值为 ETH。我需要删除所有值并保留最小 (Int) 值的代码。

预期结果:

[1546531017: ["symbol": "ETH", "amount": "1.0"], 1546531031: ["symbol": "XRP", "amount": "200.0"]]

1546531017 < 1546696330在哪里

【问题讨论】:

  • 你有嵌套的字典,看起来你想折叠内部字典中的重复条目,但不清楚应该如何驱动折叠。您是如何决定在结果中保留外部键 1546531017 而不是另一个 1546696330 键?
  • 如何判断是否有重复?只是 symbol 匹配,还是 symbolamount 必须匹配才能被视为重复?
  • @DuncanC 我需要最小密钥并删除所有其他包含重复符号的密钥。
  • @vacawama amount 没关系。我需要删除所有重复的符号并留下最小的一个。
  • 我会构建一个字典,其中键是符号,值是“Int”。如果存在,则在需要时替换(如果它比当前的最小)。然后,只保留值,并过滤 dict(删除未使用的,或从保留的键中构造一个新的)。没有高级 Swift 函数,解释我的逻辑:pastebin.com/gprc23X0

标签: swift sorting dictionary duplicates


【解决方案1】:

@Larme 在 cmets 中描述的算法是解决这个问题的直接方法。

创建一个[String:Int] 字典,表示您要保留的原始字典中的值。 keysymbolvalue 是您要保留的Int

然后使用此字典构造最终字典,使用keep 的值从原始字典中选择条目。

代码如下:

// original dictionary
let dict: [Int:[String:String]] = [1546696330: ["symbol": "ETH", "amount": "1.0"], 1546531017: ["symbol": "ETH", "amount": "1.0"], 1546531031: ["symbol": "XRP", "amount": "200.0"]]

// Dictionary mapping symbol to Int of values we want to keep
var keep = [String:Int]()

// Loop on original dictionary deciding on whether to keep this symbol
// based on how its Int compares to the one we've already kept
for (key, value) in dict {
    guard let symbol = value["symbol"] else { continue }
    if let ekey = keep[symbol] {
        // We already have this one, so keep the minimum of the two
        keep[symbol] = min(key, ekey)
    } else {
        keep[symbol] = key
    }
}

// Show the keep dictionary
print(keep)
["XRP": 1546531031, "ETH": 1546531017]
// The final dictionary
var dict2 = [Int:[String:String]]()

// Fill the final dictionary based upon the values we chose to keep
for value in keep.values {
    dict2[value] = dict[value]
}

// Show the final result
print(dict2)
[1546531031: ["amount": "200.0", "symbol": "XRP"], 1546531017: ["amount": "1.0", "symbol": "ETH"]]

reduce(into:)创建keep

如果可读性差一点,那就更 Swifty 使用 reduce(into:) 创建 keep 字典:

let keep: [String:Int] = dict.reduce(into: [:]) {
    guard let symbol = $1.value["symbol"] else { return }
    $0[symbol] = min($0[symbol, default: $1.key], $1.key)
}

使用filter() 创建最终字典:

或者,您可以通过像这样过滤原始字典来在一行中创建最终字典:

let dict2 = dict.filter { keep.values.contains($0.key) }

【讨论】:

  • 这种创建 keep 字典的方法可能比公认的答案更有效,因为它允许直接查找 O(1) 的重复项,而不是使用 first(where:) 来查找重复,即 O(n)。随着字典大小的增加,这将变得更加重要。
【解决方案2】:

这将删除具有较大 int 值的重复项

let dict:[Int:[String:String]] = [ 1546531017: ["symbol": "ETH", "amount": "1.0"], 1546531031: ["symbol": "XRP", "amount": "200.0"],1546696330: ["symbol": "ETH", "amount": "1.0"]]
var dict2:[Int:[String:String]] = [:]

dict.forEach({ (key, value) in
    if let item = dict2.first(where: {value["symbol"] == $1["symbol"]}) {
        if (key < item.key) {
            dict2[item.key] = nil
            dict2[key] = value
        }
    } else {
        dict2[key] = value
    }
})

【讨论】:

    猜你喜欢
    • 2013-07-10
    • 2021-08-09
    • 2021-12-29
    • 1970-01-01
    • 2018-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-04
    相关资源
    最近更新 更多