嵌套数组上的 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
如果 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<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
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 适用于此。 我的评论并不是要选择一个不必要的复杂答案。您的回答不能解决这个问题。你的回答不完整。这个问题比你想象的要复杂。 我的答案是一个解决方案,并且是完整的。这是解决所描述问题的最简单方法。你似乎让事情变得比实际更复杂。以上是关于嵌套数组上的 Swift 相等运算符的主要内容,如果未能解决你的问题,请参考以下文章