Swift equality operator on nested arrays

前端 未结 2 962
太阳男子
太阳男子 2020-11-27 07:53

Why does the last statement fail to compile with the error: Binary operator \'==\' cannot be applied to two \'[[Simple]]’ operands, and is there a way way to mo

相关标签:
2条回答
  • 2020-11-27 08:05

    Update: Conditional conformance has been implemented in Swift 4.1. In particular:

    The standard library types Optional, Array, and Dictionary now conform to the Equatable protocol when their element types conform to Equatable. ...

    (from the Swift CHANGELOG).

    Arbitrarily nested arrays of Equatable elements are Equatable now and can be compared with ==. Your code

    var x: [[Simple]] = [[Simple(message: "a")], [Simple(message: "b")]]
    var y: [[Simple]] = [[Simple(message: "a")], [Simple(message: "b")]]
    x == y
    

    compiles in Xcode 9.3 if Simple is Equatable.


    (Old answer:) The reason is similar as in Why is Equatable not defined for optional arrays. Arrays can be compared with == if the element type is Equatable:

    /// Returns true if these arrays contain the same elements.
    public func ==<Element : Equatable>(lhs: [Element], rhs: [Element]) -> Bool
    

    That's why

    var a: [Simple] = [Simple(message: "a")]
    var b: [Simple] = [Simple(message: "a")]
    a == b // -> true
    

    compiles.

    But even for equatable types T, Array<T> does not conform to the Equatable protocol, compare Why can't I make Array conform to Equatable?. Therefore, in

    var x: [[Simple]] = [[Simple(message: "a")], [Simple(message: "b")]]
    var y: [[Simple]] = [[Simple(message: "a")], [Simple(message: "b")]]
    x == y // -> ERROR! Binary operator '==' cannot be applied to two '[[Simple]]’ operands
    

    x and y are arrays with the element type [Simple] which does not conform to the Equatable protocol, and there is no matching == operator.

    You could define a generic == operator for simply nested arrays as

    func ==<Element : Equatable> (lhs: [[Element]], rhs: [[Element]]) -> Bool {
        return lhs.count == rhs.count && !zip(lhs, rhs).contains {$0 != $1 }
    }
    

    or more simply (as suggested by @kennytm):

    func ==<Element : Equatable> (lhs: [[Element]], rhs: [[Element]]) -> Bool {
        return lhs.elementsEqual(rhs, by: ==)
    }
    

    This makes x == y compile and work as expected. At present, there seems to be no way to define a == operator on arbitrarily nested arrays.

    0 讨论(0)
  • 2020-11-27 08:25

    You can do it by implementing a == function for it, like following:

    func == (lhs: [[Simple]], rhs: [[Simple]]) -> Bool {
        //your code
    }
    
    0 讨论(0)
提交回复
热议问题