嵌套数组上的 Swift 相等运算符

标签 swift

为什么最后一条语句无法编译并出现错误:二元运算符'=='不能应用于两个'[[Simple]]'操作数,有没有办法修改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 中实现。特别是:

The standard library types Optional, Array, and Dictionary now conform to the Equatable protocol when their element types conform to 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

在 Xcode 9.3 中编译 if SimpleEquatable .

<小时/>

(旧答案:) 原因与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

编译。

但即使对于可等同类型 T , Array<T> 不符合Equatable协议(protocol),比较 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协议(protocol),并且没有 匹配==运算符。

您可以定义一个通用的 ==简单嵌套数组的运算符为

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 相等运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39923357/

相关文章:

ios - 使用 swift 4 在 VIPER 中进行 dataTaskWithURL 崩溃单元测试

ios - 身份验证后 Firebase uid 返回 nil (Swift)

ios - 使用 UICollectionViewDiffableDataSource 和 NSFetchedResultsController 重新排序单元格

swift - 删除 UIView 后重置其他组件的约束

ios - UIView 的动画约束(作为主视图的 subview )

ios - 如何在 subview 中获取 UIImage 的来源

ios - 从父级到子级的 Swift Pass 事件

ios - 如何在 swift 4.1 中从服务器获取图像

swift - UISearchBar 为取消按钮设置不同的色调

swift - 格式化后从字符串中删除空格