【问题标题】:Remove duplicate values from a dictionary in Swift 3从 Swift 3 中的字典中删除重复值
【发布时间】:2017-09-04 11:46:09
【问题描述】:

您好,我有一本字典,我只想像这样删除重复值(使用它们的键):

var myDict : [Int:String] = [1:"test1", 2:"test2", 3:"test1", 4:"test4"]

期望的输出:

[1: "test1", 2: "test2", 4: "test4"]

【问题讨论】:

    标签: ios dictionary swift3


    【解决方案1】:

    您可以使用此代码

    let newDict = myDict.keys.sorted().reduce([Int:String]()) { (res, key) -> [Int:String] in
        guard let value = myDict[key], !res.values.contains(value) else { return res }
        var res = res
        res[key] = value
        return res
    }
    

    请记住,字典没有排序,所以输出可能是这样的

    [2: "test2", 4: "test4", 1: "test1"]
    

    请参考 @Duncan 提供的answer 以获得更快的解决方案。

    【讨论】:

    • 请记住 - 如果您正在动态构建字典,如果您已经拥有该条目,最好不要首先添加它,而不是添加然后删除
    • @Russell:是的,这就是我正在做的事情。
    • 已确认。我刚刚编写了一个测试程序,它在包含 10000 个键/值对的字典上运行您的代码和我的版本。您的代码运行大约需要 23 秒。我的耗时约 0.021 秒,或者快 1000 倍多一点。时间差会随着源字典的大小呈几何级数增长。
    • 我用字典中的 100,000 个条目重新运行了测试,我的代码花费了大约 0.024 秒(比 10,000 个条目多千分之三秒),在撰写本文时,上面的代码仍在运行,大约 10 分钟后。根据我的估计,大约需要 38 分钟。 N 平方算法对于大型数据集非常不好。
    • 我在骑自行车时进行了 100,000 次入门测试。此答案中的代码运行时间为 49.9 分钟,而我的版本为 0.024 秒。
    【解决方案2】:
    var myDict: [Int:String] = [1:"test1", 2:"test2", 3:"test1", 4:"test4"]
    
    var result: [Int:String] = [:]
    for (key, value) in myDict {
        if !result.values.contains(value) {
            result[key] = value
        }
    }
    
    print(result)
    

    【讨论】:

      【解决方案3】:

      这是另一种方法

      var myDict : [Int:String] = [1:"test1", 2:"test1", 3:"test1", 4:"test4", 5:"test4"]
      
      var newDict:[Int: String] = [:]
      
      for (key, value) in myDict {
          print(key, value)
      
          let keys = myDict.filter {
              return $0.1.contains(value)
              }.map {
                  return $0.0
          }
      
          if keys.first == key {
              newDict[key] = value
          }
      }
      
      print(newDict)
      

      【讨论】:

        【解决方案4】:

        在我看来,所有其他答案都将具有 O(n^2) 性能。

        这是一个应该在 O(n) 时间内运行的解决方案:

        var sourceDict = [1:"test1", 2:"test2", 3:"test1", 4:"test4"]
        
        var uniqueValues = Set<String>()
        var resultDict = [Int:String](minimumCapacity: sourceDict.count)
        
        //The reserveCapacity() function doesn't exist for Dictionaries, as pointed
        //out by Hamish in the comments. See the initializer with minimumCapacity, 
        //above. That's the way you have to set up a dictionary with an initial capacity.
        //resultDict.reserveCapacity(sourceDict.count)
        
        for (key, value) in sourceDict {
          if !uniqueValues.contains(value) {
            uniqueValues.insert(value)
            resultDict[key] = value
          }
        }
        

        对于小型字典,差异是微不足道的,但如果你有一个包含数百(或数千)键/值对的字典,那么 n^2 算法的性能开始变得真的很差。

        【讨论】:

        • 感谢@Duncan C 的评论,我实际上使用的是一个小字典,所以算法的复杂性对我来说并不重要。但是在使用庞大的字典时我会注意它!干杯。
        • 刚刚尝试了你的解决方案,我收到一个错误 Value of type '[Int : String]' has no member 'reserveCapacity',也许初始化程序签名在 Swift 3 中已更改为其他内容
        • 请注意,使用 N-Squared 算法所需的时间在大约 30 个项目时开始急剧增长。它不需要一个非常大的数据集来显眼所需的时间。请参阅我对 Appz 答案的最后评论。
        • Dictionary 没有 reserveCapacity(_:) 方法(尽管它确实应该)——您可能打算改用 init(minimumCapacity:) 初始化程序。
        • @Hamish,是的,我意识到当我尝试实际运行它时,但懒得编辑我的答案。谢谢你让我诚实。
        猜你喜欢
        • 1970-01-01
        • 2010-11-30
        • 1970-01-01
        • 1970-01-01
        • 2019-09-26
        • 1970-01-01
        • 2015-01-18
        • 1970-01-01
        • 2018-04-14
        相关资源
        最近更新 更多