为什么最后一个语句无法编译并显示错误:Binary operator '==' cannot be applied to two '[[Simple]]’ operands,并且有一种方法可以修改Simple结构或扩展==运算符,以便能够对嵌套数组(或字典)执行相等性检查?

var i1: [Int] = [1]
var i2: [Int] = [1]
i1 == i2 // -> true


var i3: [[Int]] = [[1], [2]]
var i4: [[Int]] = [[1], [2]]
i3 == i4 // -> true


struct Simple: Equatable, Hashable {
    let message: String

    var hashValue: Int {
        return message.hashValue
    }
}
func ==(lhs: Simple, rhs: Simple) -> Bool {
    return lhs.message == rhs.message
}

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

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

最佳答案

更新:条件一致性已在Swift 4.1中实现。尤其是:


  现在,标准库类型Optional,Array和Dictionary的元素类型符合Equatable时,它们便符合Equatable协议。 ...


(来自Swift CHANGELOG)。

现在,Equatable元素的任意嵌套数组为Equatable
可以与==进行比较。您的密码

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


如果SimpleEquatable,则在Xcode 9.3中编译。



(旧答案:)
原因与Why is Equatable not defined for optional arrays中类似。如果元素类型为==,则可以将数组与Equatable进行比较:

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


这就是为什么

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


编译。

但是,即使对于等于类型的TArray<T>不符合Equatable协议,请比较Why can't I make Array conform to Equatable?。因此,在

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


xy是元素类型为[Simple]的数组
不符合Equatable协议,并且没有
匹配的==运算符。

您可以为简单的嵌套数组定义通用==运算符,如下所示:

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


或更简单(如@kennytm建议):

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


这使得x == y可以按预期进行编译和工作。目前看来
不能在任意嵌套的数组上定义==运算符。

关于swift - 嵌套数组上的Swift等于运算符,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41201291/

10-12 14:42