如何比较两个对象数组?

Posted

技术标签:

【中文标题】如何比较两个对象数组?【英文标题】:How to compare two array of objects? 【发布时间】:2016-08-26 07:54:44 【问题描述】:

我有一个 A 类:

class A 
   var identifier: String?
   var quantity: Int = 0

两个 A 实例数组:

var array1: [A] = [a1, a2, a3, a4]
var array2: [A] = [a5, a6, a7, a8]

我不知道哪种检查方法最好: array1==array2 if a1.identifier == a5.identifier, a2.identifier == a6.identifier, a3.identifier==a7.identifier, a4.identifier==a8.identifier 在 Swift 中。

请帮帮我...

【问题讨论】:

array1 和 array2 将始终具有相同的大小?显示数组计数也可以检查吗?还是检查数组中每个元素的属性? @ddb: 抱歉,他们的计数是随机的 所以如果他们有不同的计数,他们应该被归类为不等,对吧? 你认为什么是平等的?如果它们的长度相同?如果他们有相同的项目?所有项目都必须在同一个索引处吗? @ddb: 是的...我明白了,但是另一个案例怎么样@-@ 【参考方案1】:

你可以这样试试:

let result = zip(array1, array2).enumerated().filter() 
    $1.0 == $1.1
.map$0.0

【讨论】:

@Rahul Tripathi,亲爱的 Rahul Tripathi,您能解释一下您的代码吗?这很有趣,但我无法理解。这是我的代码 let array1: [Int] = [1, 2, 3, 4] let array2: [Int] = [5, 6, 7, 8] let result = zip (array1, array2).enumerated().filter() $1.0 == $1.1 .map$0.0 print(result) 事件如果可行,它看起来像是从某个地方复制粘贴代码,没有任何代码解释!.@Rahul Tripathi 我认为这不是一个好的解决方案。它仅适用于一种情况,即当两个数组按相同顺序排序时。 这是一个错误的答案,因为 [1,2,3] 在这个比较中等于 [1,2,3,4](zip 选择最短数组的长度)【参考方案2】:

斯威夫特 4

下面的方法使它更容易。

方法 1 - 使用 Equatable 协议

第 1 步 - 使您的类 'A' 等价如下

extension A: Equatable 
    static func ==(lhs: A, rhs: A) -> Bool 
        // Using "identifier" property for comparison
        return lhs.identifier == rhs.identifier
    

Step2 - 按升序或降序对数组进行排序

let lhsArray = array1.sorted(by:  $0.identifier < $1.identifier )
let rhsArray = array2.sorted(by:  $0.identifier < $1.identifier )

Step3 - 使用 == 或 elementsEqual 比较

let isEqual = lhsArray == rhsArray

let isEqual = lhsArray.elementsEqual(rhsArray, by:  $0 == $1 )

方法 2(无 Equatable 协议)

第 1 步 - 按照方法 1 第 2 步中的描述对数组进行排序

第 2 步 - 使用 elementsEqual

lhsArray.elementsEqual(rhsArray, by:  $0.identifier == $1.identifier )

阅读更多关于Array Comparison here

【讨论】:

elementsEqual 是一个很棒的小功能,以前从未遇到过,但这正是我需要的:) 感谢您的回复@Anand。但是,如果我想用相等的对象创建新数组,我该怎么办? @ErkamKUCET 你可以使用 array.filter 方法。 @Anand 好的,实际上,我的问题是我有两个相同类型的数组,我想从这些数组中创建一个具有相同数组的新数组。 @ErkamKUCET:你应该通过official doc。有许多内置功能可供您使用。如果您仍然找不到正确的方法,请在此处作为新问题提出。【参考方案3】:

假设你的数据是这样的:

struct Person
    
        let name: String
        let id:  Int
    

    var people1 = [
        Person(name: "Quang Hà", id: 42),
        Person(name: "Lý Hải", id: 23),
        Person(name: "Maria", id: 99)
    ]

    var people2 = [
        Person(name: "Maria yyy", id: 99),
        Person(name: "Billy", id: 42),
        Person(name: "David", id: 23)
    ]

这是比较两个有id的人数组的方法:

func areArrayPeopleEqual(people1:[Person], people2: [Person]) -> Bool 
    var array1 = people1
    var array2 = people2

    // Don't equal size => false
    if array1.count != array2.count 
        return false
    

    // sort two arrays
    array1.sortInPlace()  $0.id > $1.id 
    array2.sortInPlace() $0.id > $1.id 

    // get count of the matched items
    let result = zip(array1, array2).enumerate().filter() 
        $1.0.id == $1.1.id
        .count

    if result == array1.count 
        return true
    

    return false

【讨论】:

没有理由使用.enumerate() 来获取匹配项的计数,但是过滤器看起来像 $0.0.id == $0.1.id 【参考方案4】:

首先我们扩展 Equatable 类,以获得 DRY 代码,而不是如果 2 个数组始终具有相同的大小,或者如果至少第一个是

请注意,您正在使用可选项,您可能必须先解开它们。

class A 
    var identifier: String?
    var quantity: Int = 0

    init(identifier: String, quantity: Int) 
        self.identifier = identifier
        self.quantity = quantity
    


let a1: A = A(identifier: "1", quantity: 1)
let a2: A = A(identifier: "2", quantity: 2)
let a3: A = A(identifier: "3", quantity: 3)
let a4: A = A(identifier: "4", quantity: 4)

let a5: A = A(identifier: "1", quantity: 1)
let a6: A = A(identifier: "2", quantity: 2)
let a7: A = A(identifier: "3", quantity: 3)
let a8: A = A(identifier: "4", quantity: 4)

var array1: [A] = [a1, a2, a3, a4]
var array2: [A] = [a5, a6, a7, a8]

func areEquals(array1: [A], array2: [A]) -> Bool 
    if array1.count < array2.count 
        return false
    
    for i in 0...array2.count - 1 
        if array1[i] != array2[i] 
            return false
        
    
    return true



extension A: Equatable 
    static func ==(lhs: A, rhs: A) -> Bool 
        //you can choose how and when they should be equals
        return lhs.identifier == rhs.identifier
    

【讨论】:

【参考方案5】:

如果您有一些参数要比较,可以使用此方法:

let difference = currentObjects
    .filter( currentObject in
        !(newObjects
            .contains(where:  $0.identifier == currentObject.identifier ))
    )

【讨论】:

【参考方案6】:

我在https://www.hackingwithswift.com/example-code/language/how-to-find-the-difference-between-two-arrays找到了这个非常简单的解决方案

extension Array where Element: Hashable 
func difference(from other: [Element]) -> [Element] 
    let thisSet = Set(self)
    let otherSet = Set(other)
    return Array(thisSet.symmetricDifference(otherSet))
 


let names1 = ["a1", "A4", "a3", "a4"]//["John", "Paul", "Ringo"]
let names2 = ["a1", "a5", "a4","a1.1"]//["Ringo", "George"]
let difference = names1.difference(from: names2)

【讨论】:

【参考方案7】:

试试这个代码,让我知道它是否有效

func toDictionary<E, K, V>(
    array:       [E],
    transformer: (element: E) -> (key: K, value: V)?)
    -> Dictionary<K, V>

    return array.reduce([:]) 
        (var dict, e) in
        if let (key, value) = transformer(element: e)
        
            dict[key] = value
        
        return dict
    

然后您可以执行如下检查

let areEqual = array1.count == array2.count;
if areEqual 
    let dict1 = toDictionary(array1)  ($0.identifier, $0.quantity) 
    let dict2 = toDictionary(array2)  ($0.identifier, $0.quantity) 
    areEqual = NSDictionary(dictionary: dict1).isEqualToDictionary(dict2)

print(areEqual)

免责声明:函数toDictionary 已采用here 的形式

【讨论】:

以上是关于如何比较两个对象数组?的主要内容,如果未能解决你的问题,请参考以下文章

如何比较两个对象数组?

如何在 es6 中仅比较和过滤两个对象数组中不匹配的数组

如何比较两个对象数组以删除重复项?

如何比较两个数组的对象?

java如何判断两个二维对象数组相等,让后打印一句话。

如何比较两个数组并通过完整迭代删除重复的对象