arrays - 从多维数组中删除重复项

标签 arrays swift value-type 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
    }
}

线阵

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 数组与 Int 数组
  • 如何从多维数组中删除重复项?

我目前正在使用 Swift 4.0.2

最佳答案

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 可用)中,Array<Element>现在符合 Equatable当它 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 中按预期编译和运行,产生结果 [[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 – 由于 ==,编译器认为它不明确IndexSet 的重载和 IndexPath (两者都是 ExpressibleByArrayLiteral )。但是 Swift 应该将数组文字默认为 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 }
  }
}

这里我们使用一个集合来存储我们已经看到的元素,省略了我们已经插入其中的任何元素。这也允许我们使用 filter(_:) , as @Alexander points out .

in Swift 4.2 , Array也有条件地符合 Hashable当它 ElementHashable :

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.

关于arrays - 从多维数组中删除重复项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50275692/

相关文章:

javascript - 如何按正整数或负整数对数组进行排序

ios标签栏 Controller 动画

IOS:SDWebImage仅在远程图像未更改时缓存

c# - 与很少使用的值类型初始化混淆

scala - 如何将宏用于简洁、类型安全、未装箱的枚举?

java - 将 Java 中的 ArrayList.toArray() 类型转换为普通数组

谁能帮我理解这段代码有什么问题?

c# - 为什么我需要通过引用我的交换函数来传递字符串?

php - array_diff不返回预期的结果

swift - 以编程方式将 View 添加到 StackView 不执行任何操作