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

Posted

技术标签:

【中文标题】嵌套数组上的 Swift 相等运算符【英文标题】:Swift equality operator on nested arrays 【发布时间】:2015-10-27 20:22:46 【问题描述】:

为什么最后一条语句无法编译并出现错误: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 中得到解决。 【参考方案1】:

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

当它们的元素类型符合 Equatable 时,标准库类型 Optional、Array 和 Dictionary 现在符合 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&lt;T&gt; 不符合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 可以按预期编译和工作。目前看来 无法在任意嵌套数组上定义== 运算符。

【讨论】:

也许将实现更新为lhs.elementsEqual(rhs, by: ==) 建议:由于github.com/apple/swift-evolution/blob/master/proposals/…未包含在Swift 4中,请更新答案 @PetroKorienev:完成! – SE-0143 尚未实现,但可等元素数组的特殊情况已经实现,这实际上足以解决 this 问题。【参考方案2】:

您可以通过为它实现一个== 函数来做到这一点,如下所示:

func == (lhs: [[Simple]], rhs: [[Simple]]) -> Bool 
    //your code

【讨论】:

很抱歉投了反对票,但这个问题比您的答案所暗示的要复杂得多。 @Jeff 你有权发表你的意见,但我总是更喜欢简单的解决方案而不是复杂的解决方案。 YAGNI 适用于此。 我的评论并不是要选择一个不必要的复杂答案。您的回答不能解决这个问题。你的回答不完整。这个问题比你想象的要复杂。 我的答案是一个解决方案,并且是完整的。这是解决所描述问题的最简单方法。你似乎让事情变得比实际更复杂。

以上是关于嵌套数组上的 Swift 相等运算符的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 中使用相同的运算符(===)

在 2 个空数组的这个松散相等比较中发生了啥

Python开发---29numpy

嵌套for循环中的python数组[重复]

Swift 学习- 03 -- 基本运算符

Js展开运算符和嵌套数组