数组是等价的吗?我可以使用它们进行比较吗==
在 Swift 4.1 之前,Array
不符合Equatable
. ==
然而,将两个数组与Equatable
元素进行比较时存在重载,这使得它能够编译:
if ["1", "2"] == ["1", "2"] { // using <T : Equatable>(lhs: [T], rhs: [T]) -> Bool
print("true")
}
然而,在 Swift 4.1(Xcode 9.3 中可用)中,当它Array<Element>
符合. 此更改在更改日志中给出:Equatable
Element
Equatable
斯威夫特 4.1
[...]
- SE-0143标准库类型
Optional
, Array
, ArraySlice
,ContiguousArray
和Dictionary
现在Equatable
在其元素类型符合时符合协议Equatable
。这允许==
操作员进行组合(例如,可以将两个类型的值[Int : [Int?]?]
与进行比较==
),以及使用为Equatable
元素类型定义的各种算法,例如index(of:)
.
您的示例multiDimArr.removeDups()
在 4.1 中按预期编译和运行,产生结果[[1, 2, 3], [1, 2, 4]]
。
在 Swift 4.0.3 中,您可以通过添加另一个removeDups()
嵌套数组的重载来破解它:
extension Array {
func removeDups<T : Equatable>() -> [Element] where Element == [T] {
var result = [Element]()
for element in self{
if !result.contains(where: { element == $0 }) {
result.append(element)
}
}
return result
}
}
let multiDimArr = [[1, 2, 3], [1, 2, 3], [1, 2, 4]]
print(multiDimArr.removeDups()) // [[1, 2, 3], [1, 2, 4]]
不幸的是,这确实会导致一些代码重复,但至少您可以在更新到 4.1 时摆脱它。
这个例子不能在 4.0.3 或 4.1 中编译的事实:
if [1, 2] == [1, 2] { // error: Ambiguous use of operator '=='
print("true")
}
是由于错误SR-5944造成的——编译器认为它是模棱两可的,因为and (两者都是)的==
重载。但是 Swift 应该默认一个数组字面量来解决歧义。IndexSet
IndexPath
ExpressibleByArrayLiteral
Array
说:
if [1, 2] as [Int] == [1, 2] {
print("true")
}
或不导入Foundation
解决问题。
最后,值得注意的是,如果类型也是,removeDups()
则可以提高的性能,允许它以线性时间而不是二次时间运行:Element
Hashable
extension Array where Element : Hashable {
func removeDups() -> [Element] {
var uniquedElements = Set<Element>()
return filter { uniquedElements.insert($0).inserted }
}
}
在这里,我们使用一个集合来存储我们已经看到的元素,省略了我们已经插入其中的任何元素。正如@Alexander 指出的那样filter(_:)
,这也允许我们使用。
而在 Swift 4.2中,Array
也有条件地符合Hashable
when it Element
is Hashable
:
斯威夫特 4.2
[...]
- SE-0143标准库类型
Optional
, Array
, ArraySlice
, ContiguousArray
, Dictionary
, DictionaryLiteral
, Range
, 和ClosedRange
现在Hashable
在其元素或绑定类型(视情况而定)符合时符合协议Hashable
。这使得综合Hashable
实现可用于包含这些类型的存储属性的类型。