比较可选数组

时间:2015-04-06 19:58:51

标签: swift

在游乐场中运行以下代码段会出错:

let a: [Int]? = [1,2]
let b: [Int]? = [1,2]
a == b // value of optional type '[Int]?' not unwrapped; did you mean to use '!' or '?'?

为“更简单”的可选类型做类似的事情时可以使用:

var x: Int? = 10
var y: Int?
x == y // false

第一种情况,可选数组背后的原因是什么,不被允许?为什么Swift不能首先查看是否有nil.None),如果不是,请进行实际的数组比较。

3 个答案:

答案 0 :(得分:31)

它适用于更简单类型的原因是因为有==版本为包含Equatable类型的选项定义:

func ==<T : Equatable>(lhs: T?, rhs: T?) -> Bool

虽然IntEquatable,但Array不是(因为它可能包含一些不相同的东西 - 在这种情况下它是怎么回事)。所有Equatable内容都有一个==运算符,但并非==运算符的所有内容都是Equatable

您可以专门为包含equatable类型的可选数组编写==的特例版本:

func ==<T: Equatable>(lhs: [T]?, rhs: [T]?) -> Bool {
    switch (lhs,rhs) {
    case (.Some(let lhs), .Some(let rhs)):
        return lhs == rhs
    case (.None, .None):
        return true
    default:
        return false
    }
}

您还可以将其概括为涵盖包含equatable元素的任何集合:

func ==<C: CollectionType where C.Generator.Element: Equatable>
  (lhs: C?, rhs: C?) -> Bool {
    switch (lhs,rhs) {
    case (.Some(let lhs), .Some(let rhs)):
        return lhs == rhs
    case (.None, .None):
        return true
    default:
        return false
    }
}

答案 1 :(得分:8)

添加swift 3版本的Airspeed答案:

func ==<T: Equatable>(lhs: [T]?, rhs: [T]?) -> Bool {
  switch (lhs,rhs) {
  case (.some(let lhs), .some(let rhs)):
    return lhs == rhs
  case (.none, .none):
    return true
  default:
    return false
  }
}

func ==<C: Collection where C.Iterator.Element: Equatable>(lhs: C?, rhs: C?) -> Bool {
  switch (lhs,rhs) {
  case (.some(let lhs), .some(let rhs)):
    return lhs == rhs
  case (.none, .none):
    return true
  default:
    return false
  }
}

答案 2 :(得分:-1)

Swift 4.1

更新:缺少的功能已在Swift 4.1中实现。

您的代码

let a: [Int]? = [1,2]
let b: [Int]? = [1,2]
a == b

从Xcode 9.3(Swift 4.1)开始编译并按预期工作。

旧答案

最简单的方法是不使用可选数组并使用空数组([])而不是nil - 如果您不需要区分这两种情况。

let a = [1,2]
let b = [1,2]
let c = []
a == b
b != c

当我为结构编写Equatable扩展时,它适用于我的情况。我没有使用属性categories: [Category]?,而是将其更改为categories: [Category]并将缺少的类别解析为空数组([])。