Сравнение дополнительных массивов
Выполнение следующего фрагмента кода на игровой площадке дает ошибку:
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
), а затем, если это не так, выполните фактическое сравнение массива.
Ответы
Ответ 1
Причина, по которой он работает для более простых типов, заключается в том, что существует версия ==
, которая определена для опций, которые содержат типы Equatable
:
func ==<T : Equatable>(lhs: T?, rhs: T?) -> Bool
Но пока Int
есть Equatable
, Array
не (потому что он может содержать что-то, что не является равнозначным - в этом случае, как это могло бы быть). Все вещи 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
}
}
Вы также можете обобщить это, чтобы покрыть любую коллекцию, содержащую равнозначные элементы:
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
}
}
Ответ 2
добавление быстрой версии 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
}
}
Ответ 3
Самый простой способ - не использовать дополнительный массив и использовать пустой массив ([]
) вместо nil
- в случае, если вам не нужно различать эти два случая.
let a = [1,2]
let b = [1,2]
let c = []
a == b
b != c
Он работал в моем случае, когда я писал Equatable extension для struct. Вместо использования свойства categories: [Category]?
я только что изменил его на categories: [Category]
и проанализировал отсутствующие категории как пустой массив ([]
).