Hon*_*ney 1 arrays value-type swift equatable
我写了以下扩展名来删除我的数组中的重复项.
extension Array where Element : Equatable{
func removeDups() -> [Element]{
var result = [Element]()
for element in self{
if !result.contains(element){
result.append(element)
}
}
return result
}
}
Run Code Online (Sandbox Code Playgroud)
线性阵列
let linearArr = [1,2,2,3]
linearArr.removeDups() // [1,2,3] works well!
Run Code Online (Sandbox Code Playgroud)
多维数组
let multiDimArr : [[Int]] = [[1,2,3], [1,2,3], [1,2 ,4]]
multiDimArr.removeDups() // Error!
Run Code Online (Sandbox Code Playgroud)
类型[Int]不符合Equatable
我读到这里.答案说使用阵列比较==应该可行.它不能一直工作:
作品
if (["1", "2"] == ["1", "2"]){
print("true")
}
Run Code Online (Sandbox Code Playgroud)
不行
if ([1, 2] == [1, 2]){ // ERROR!
print("true")
}
Run Code Online (Sandbox Code Playgroud)
运算符'=='的模糊使用
这很特别.我可以比较数组的Strings但不能比较数组的Ints.
我也看到了这个评论:
原因myArray1 == myArray2是NSObject符合Equatable,要求-[equals:]进行测试
不确定☝️评论是否仍然有效.
总结一下:
==StringS的数组与Ints的数组不同我正在和我一起工作 Swift 4.0.2
数组是否相等?我可以用它来比较它们吗?
==
在Swift 4.1之前,Array没有符合Equatable.然而,==有两个数组与Equatable元素进行比较的重载,这使得它能够编译:
if ["1", "2"] == ["1", "2"] { // using <T : Equatable>(lhs: [T], rhs: [T]) -> Bool
print("true")
}
Run Code Online (Sandbox Code Playgroud)
但是在Swift 4.1(Xcode 9.3中可用)中,Array<Element>现在符合Equatable它的Element符合性Equatable.更改日志中给出了此更改:
Swift 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]]
Run Code Online (Sandbox Code Playgroud)
不幸的是,这会导致一些代码重复,但至少在更新到4.1时你将能够摆脱它.
此示例无法在4.0.3或4.1中编译的事实:
if [1, 2] == [1, 2] { // error: Ambiguous use of operator '=='
print("true")
}
Run Code Online (Sandbox Code Playgroud)
是由于SR-5944的错误- 编译器认为它由于和(两者都是)的==重载而不明确.但Swift应该默认一个数组文字,解决歧义.IndexSetIndexPathExpressibleByArrayLiteralArray
说:
if [1, 2] as [Int] == [1, 2] {
print("true")
}
Run Code Online (Sandbox Code Playgroud)
或不导入Foundation解决问题.
最后,值得注意的是,removeDups()如果Element类型也可以改善性能Hashable,允许它以线性而非二次时间运行:
extension Array where Element : Hashable {
func removeDups() -> [Element] {
var uniquedElements = Set<Element>()
return filter { uniquedElements.insert($0).inserted }
}
}
Run Code Online (Sandbox Code Playgroud)
在这里,我们使用一个集合来存储我们已经看到的元素,省略我们已经插入的元素.这也允许我们使用filter(_:),正如@Alexander指出的那样.
而在斯威夫特4.2,Array也有条件地符合Hashable当其Element为Hashable:
Swift 4.2
[...]
- SE-0143标准库类型
Optional,Array,ArraySlice,ContiguousArray,Dictionary,DictionaryLiteral,Range,和ClosedRange现在符合Hashable协议时其元件或结合类型(视情况而定)符合Hashable.这使得合成Hashable实现可用于包含这些类型的存储属性的类型.