【问题标题】:Swift: HowTo get the difference between two struct-arraysSwift:如何区分两个结构数组
【发布时间】:2016-07-14 20:57:51
【问题描述】:

我有两个自定义结构数组...

struct CarStruct {
    var name : String?
    var speed : Int?
}

var allCarsArr = [CarStruct]() // should contain a lot of CarStructs
var newCarsArr = [CarStruct]() // contains only a few

我想将newCarsArr 添加到allCarsArr

但在此之前,我需要证明newCarsArr 不包含已经在allCarsArr 中的结构。

那么我怎样才能从newCarsArr 中取出不在allCarsArr 中的所有structs

【问题讨论】:

    标签: arrays swift struct filter


    【解决方案1】:

    作为使用集合的替代方法(符合 CarStructHashable),您可以满足于符合 Equatable 并简单地检查 allCarsArr 以查找要从 newCarsArr 添加的每辆车的重复项。

    /* (example of) conformance to Equatable */
    func == (lhs: CarStruct, rhs: CarStruct) -> Bool {
        return lhsName == rhsName && lhsSpeed == rhsSpeed
    }
    
    struct CarStruct : Equatable {
        var name : String?
        var speed : Int?
    }
    
    var allCarsArr = [CarStruct]()
    var newCarsArr = [CarStruct]()
    
    allCarsArr.append(CarStruct(name: "Volvo", speed: 42))
    allCarsArr.append(CarStruct(name: "BMW", speed: 50))
    newCarsArr.append(CarStruct(name: "BMW", speed: 80))
    newCarsArr.append(CarStruct(name: "BMW", speed: 50)) // <-- duplicate
    
    /* Add only cars from newCarsArr to allCarsArr if they don't 
       exist, priorly, in the latter */
    newCarsArr.forEach { allCarsArr.contains($0) ? () : allCarsArr.append($0) }
    

    但是,如果您使用大型数组,则更好的唯一性选择可能是使用符合 Hashable 并使用集合或字典(如上所示,如果 allCarsArr 变得非常大,可能会产生不需要的开销),如in Kenneth Bruno:s solution above 所述。

    【讨论】:

      【解决方案2】:

      您应该将Equatable 协议添加为您的类的扩展。这是一篇很好的文章来解释它:

      Every Value Type Should Be Equatable

      然后您可以将两个数组添加到一个 Set 中,它自然会排除重复项。您还需要遵守 Hashable 才能将值放入 Set 中,但有一个简单的技巧可以将值转换为字符串并获取其中的 hashValue

      struct CarStruct {
        var name : String?
        var speed : Int?
      }
      
      extension CarStruct: Hashable, Equatable {
        // For Hashable
        var hashValue:Int { return "\(self.name),\(self.speed)".hashValue }
      }
      
      // For Equatable
      func ==(lhs:CarStruct, rhs:CarStruct) -> Bool {
        return lhs.name == rhs.name && lhs.speed == rhs.speed
      }
      
      var allCarsArr = [CarStruct]() // should contain a lot of CarStructs
      let newCarsArr = [CarStruct]() // contains only a few
      
      allCarsArr = Array(Set<CarStruct>(allCarsArr).union(newCarsArr))
      

      【讨论】:

      • 类型还需要符合Hashable 才能被允许作为Set 的成员(或Dictionary 中的键)。 (符合Hashable 本身需要符合Equatable)。
      • 是的,当我自己想起来时,我只是想发布一个示例。谢谢!
      • 请注意,仅使用结构中属性的简单String 表示的.hashValue 属性,哈希值可能没有很好的分布,从而增加了哈希冲突的风险。可能建议使用例如DJB 哈希函数,as described in the answer to this Q&A.
      • 好电话,我在这里选择了简单的方法,但经过深思熟虑的哈希算法是一个明确的改进。
      • 您可以使用subtract 方法删除共同的项目:Set(newCarsArr).subtract(allCarsArr) 这将只为您提供newCarsArr 中的新项目
      猜你喜欢
      • 2014-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-17
      • 1970-01-01
      相关资源
      最近更新 更多