从多维数组中删除重复项
Remove duplicates from a multi-dimensional array
我编写了以下扩展程序来从我的数组中删除重复项。
extension Array where Element : Equatable{
func removeDups() -> [Element]{
var result = [Element]()
for element in self{
if !result.contains(element){
result.append(element)
}
}
return result
}
}
线阵
let linearArr = [1,2,2,3]
linearArr.removeDups() // [1,2,3] works well!
多维数组
let multiDimArr : [[Int]] = [[1,2,3], [1,2,3], [1,2 ,4]]
multiDimArr.removeDups() // Error!
Type [Int] does not conform to Equatable
我读了here。答案说使用 ==
的数组比较应该有效。它不是一直有效:
有效
if (["1", "2"] == ["1", "2"]){
print("true")
}
不起作用
if ([1, 2] == [1, 2]){ // ERROR!
print("true")
}
Ambiguous use of operator '=='
这很奇怪。我可以比较 String
的数组,但不能比较 Int
的数组。
我也看到了this comment:
原因myArray1 == myArray2
是因为NSObject
符合Equatable,调用-[equals:]
进行测试
不确定☝️评论是否仍然有效。
总结:
- 数组是否相等?我可以使用
==
来比较它们吗
- 为什么比较
String
s 数组与 Int
s 数组不同
- 如何从多维数组中删除重复项?
我目前正在与 Swift 4.0.2
合作
这是递归解决问题的地方。你考虑过递归吗?我打算用实际代码回答这个问题,但我不知道 Swift 的语法。所以,这是一些伪代码:
function removeDupes() {
buffer = array;
foreach this->elements as key => element {
if(element is type array) {
this->elements[key] = element->removeDupes();
} else {
if(!this->contains(element)) {
buffer->add(element);
}
}
}
return buffer;
}
基本上,您想测试元素本身是否为数组。如果是,那么你想调用该数组的 removeDupes() 方法(它会依次查找重复项,除非它找到另一个数组,然后它会再次调用自己)。
Are arrays equatable? Can I compare them using ==
在 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)中,当 Element
符合 [=17= 时,Array<Element>
现在符合 Equatable
].此更改is given in the changelog:
Swift 4.1
[...]
- SE-0143 The standard library types
Optional
, Array
, ArraySlice
, ContiguousArray
, and Dictionary
now conform to the Equatable
protocol when their element types conform to Equatable
. This allows the ==
operator to compose (e.g., one can compare two values of type [Int : [Int?]?]
with ==
), as well as use various algorithms defined for Equatable
element types, such as index(of:)
.
您的 multiDimArr.removeDups()
示例按预期在 4.1 中编译和 运行s,产生结果 [[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 == [=11=] }) {
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——由于 ==
对 IndexSet
和 IndexPath
的重载(两者都是 ExpressibleByArrayLiteral
).但是 Swift 应该将数组文字默认为 Array
,以解决歧义。
说:
if [1, 2] as [Int] == [1, 2] {
print("true")
}
或不导入 Foundation
可解决问题。
最后,值得注意的是,如果Element
类型也是Hashable
,可以提高removeDups()
的性能,允许它运行线性,而不是比二次时间:
extension Array where Element : Hashable {
func removeDups() -> [Element] {
var uniquedElements = Set<Element>()
return filter { uniquedElements.insert([=14=]).inserted }
}
}
这里我们使用一个集合来存储我们已经看到的元素,省略了我们已经插入其中的任何元素。这也让我们可以使用 filter(_:)
, .
而in Swift 4.2,Array
在其Element
为Hashable
时也有条件地符合Hashable
:
Swift 4.2
[...]
- SE-0143 The standard library types
Optional
, Array
, ArraySlice
, ContiguousArray
, Dictionary
, DictionaryLiteral
, Range
, and ClosedRange
now conform to the Hashable
protocol when their element or bound types (as the case may be) conform to Hashable
. This makes synthesized Hashable
implementations available for types that include stored properties of these types.
我编写了以下扩展程序来从我的数组中删除重复项。
extension Array where Element : Equatable{
func removeDups() -> [Element]{
var result = [Element]()
for element in self{
if !result.contains(element){
result.append(element)
}
}
return result
}
}
线阵
let linearArr = [1,2,2,3]
linearArr.removeDups() // [1,2,3] works well!
多维数组
let multiDimArr : [[Int]] = [[1,2,3], [1,2,3], [1,2 ,4]]
multiDimArr.removeDups() // Error!
Type [Int] does not conform to Equatable
我读了here。答案说使用 ==
的数组比较应该有效。它不是一直有效:
有效
if (["1", "2"] == ["1", "2"]){
print("true")
}
不起作用
if ([1, 2] == [1, 2]){ // ERROR!
print("true")
}
Ambiguous use of operator '=='
这很奇怪。我可以比较 String
的数组,但不能比较 Int
的数组。
我也看到了this comment:
原因myArray1 == myArray2
是因为NSObject
符合Equatable,调用-[equals:]
进行测试
不确定☝️评论是否仍然有效。
总结:
- 数组是否相等?我可以使用
==
来比较它们吗
- 为什么比较
String
s 数组与Int
s 数组不同
- 如何从多维数组中删除重复项?
我目前正在与 Swift 4.0.2
这是递归解决问题的地方。你考虑过递归吗?我打算用实际代码回答这个问题,但我不知道 Swift 的语法。所以,这是一些伪代码:
function removeDupes() {
buffer = array;
foreach this->elements as key => element {
if(element is type array) {
this->elements[key] = element->removeDupes();
} else {
if(!this->contains(element)) {
buffer->add(element);
}
}
}
return buffer;
}
基本上,您想测试元素本身是否为数组。如果是,那么你想调用该数组的 removeDupes() 方法(它会依次查找重复项,除非它找到另一个数组,然后它会再次调用自己)。
Are arrays equatable? Can I compare them using
==
在 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)中,当 Element
符合 [=17= 时,Array<Element>
现在符合 Equatable
].此更改is given in the changelog:
Swift 4.1
[...]
- SE-0143 The standard library types
Optional
,Array
,ArraySlice
,ContiguousArray
, andDictionary
now conform to theEquatable
protocol when their element types conform toEquatable
. This allows the==
operator to compose (e.g., one can compare two values of type[Int : [Int?]?]
with==
), as well as use various algorithms defined forEquatable
element types, such asindex(of:)
.
您的 multiDimArr.removeDups()
示例按预期在 4.1 中编译和 运行s,产生结果 [[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 == [=11=] }) {
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——由于 ==
对 IndexSet
和 IndexPath
的重载(两者都是 ExpressibleByArrayLiteral
).但是 Swift 应该将数组文字默认为 Array
,以解决歧义。
说:
if [1, 2] as [Int] == [1, 2] {
print("true")
}
或不导入 Foundation
可解决问题。
最后,值得注意的是,如果Element
类型也是Hashable
,可以提高removeDups()
的性能,允许它运行线性,而不是比二次时间:
extension Array where Element : Hashable {
func removeDups() -> [Element] {
var uniquedElements = Set<Element>()
return filter { uniquedElements.insert([=14=]).inserted }
}
}
这里我们使用一个集合来存储我们已经看到的元素,省略了我们已经插入其中的任何元素。这也让我们可以使用 filter(_:)
,
而in Swift 4.2,Array
在其Element
为Hashable
时也有条件地符合Hashable
:
Swift 4.2
[...]
- SE-0143 The standard library types
Optional
,Array
,ArraySlice
,ContiguousArray
,Dictionary
,DictionaryLiteral
,Range
, andClosedRange
now conform to theHashable
protocol when their element or bound types (as the case may be) conform toHashable
. This makes synthesizedHashable
implementations available for types that include stored properties of these types.