【问题标题】:Swift error comparing two arrays of optionals比较两个选项数组的Swift错误
【发布时间】:2015-03-03 20:34:34
【问题描述】:

我在下一个 Swift 代码中遇到编译错误

var x:Array<Int?> = [1,2]
var y:Array<Int?> = [1,2]
if x == y {  // Error
}

如果两个数组都是Array&lt;Int&gt;,它可以正常工作,但如果其中至少一个是可选的,则会引发如下错误:

二元运算符“==”不能应用于两个Array&lt;Int?&gt; 操作数

我几个月前提交了一份错误报告,但没有得到答复。它仍然出现在 Swift 1.2 中。

为什么会这样?

【问题讨论】:

  • 整数?不是可以是nil 的Int,它是一个可选的,当不是nil 时可以是Int。那么,Int 和 Int 呢?是无法比较的不同类型。
  • 几个月前我也向 Swift 提交了几个错误,但也没有反馈。我计算了一下,Apple 每天在雷达上收到大约 9500 个错误报告。所以他们可能按(高)数字工作......
  • @sasquatch 你说的是真的,但不是真正的根本原因。这里没有非可选项,问题在于可选项缺少Equatable 一致性。
  • @sasquatch 你基本上是对的,但你实际上可以比较IntInt?(我刚试过)。这就是让我困惑的地方。
  • @sangonz 严格来说,当您将IntInt? 进行比较时,发生的事情是 Swift 隐式地​​将非可选内容包装在可选内容中,然后比较两个 Int?s ...... this article 了解更多信息。

标签: swift


【解决方案1】:

这里的问题是具有== 运算符的东西与“平等”的东西之间的区别。

OptionalArray 都有一个 == 运算符,当它们包含的内容相等时,它就可以工作:

// if T is equatable, you can compare each entry for equality
func ==<T : Equatable>(lhs: [T], rhs: [T]) -> Bool
// if T is equatable, you can compare the contents, if any, for equality
func ==<T : Equatable>(lhs: T?, rhs: T?) -> Bool

let i: Int? = 1
let j: Int = 1
i == j          // fine, Int is Equatable
["a","b"] == ["a","b"]  // and so is String

但它们本身并不符合Equatable。这是有道理的,因为您可以在其中放置非等值类型。但是这样做的结果是,如果一个数组包含一个不可相等的类型,那么== 将不起作用。由于可选项不是Equatable,因此当您将可选项放入数组时就是这种情况。

如果你尝试比较一个数组,你会得到同样的结果:

let a = [[1,2]]
let b = [[1,2]]
a == b  // error: `==` can’t be applied to `[Array<Int>]`

如果你想对它进行特殊处理,你可以将== 用于可选数组:

func ==<T: Equatable>(lhs: [T?], rhs: [T?]) -> Bool {
    if lhs.count != rhs.count { return false }
    for (l,r) in zip(lhs,rhs) {
        if l != r { return false }
    }
    return true
}

举个反例,因为Set 要求其内容是可散列的(因此是可等价的),它可以是可等价的:

let setarray: [Set<Int>] = [[1,2,3],[4,5,6]]
setarray == [[1,2,3],[4,5,6]]  // true

【讨论】:

  • 我很困惑:== 你在这里粘贴的第二个实现,难道不是暗示,如果我有两个类型为 [Int]? 的数组,你可以比较它们吗?但实际上它失败并迫使你打开它们。
  • @DánielNagy == 是可选的== 版本的签名。但是仅仅因为可选项有一个== 运算符,not 就意味着它们是Equatable。为了符合Equatable,该类型需要一个不合格的== 运算符,而可选版本仅适用于包含可等价类型的可选项(如果包含的类型不是可等价的,该怎么办?)。不幸的是,我无法粘贴不存在的代码来显示这个:-)
  • 这正是我所缺少的。我假设答案中的最后一个函数已经在 Swift 中实现了。谢谢!
  • 这里是 == 实现的另一种表述,其灵感来自 WWDC 2015 的面向协议的编程演讲:return lhs.count == rhs.count &amp;&amp; !zip(lhs, rhs).contains { $0 != $1 }
猜你喜欢
  • 2019-02-02
  • 1970-01-01
  • 1970-01-01
  • 2015-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多