【问题标题】:Swift equality operator on nested arrays嵌套数组上的 Swift 相等运算符
【发布时间】: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 中得到解决。

标签: swift


【解决方案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

如果 Simple 是 Equatable,则在 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

编译。

但即使对于可等式类型T,Array&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

x 和 y 是元素类型为 [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 适用于此。
  • 我的评论并不是要选择一个不必要的复杂答案。您的回答不能解决这个问题。你的回答不完整。这个问题比你想象的要复杂。
  • 我的答案是一个解决方案,并且是完整的。这是解决所描述问题的最简单方法。你似乎让事情变得比实际更复杂。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-07
  • 1970-01-01
  • 2012-02-03
  • 2017-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多