我可能有一个像下面这样的数组:

[1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]

或者,实际上,任何类似类型的数据部分的序列。我要做的是确保每个相同的元素只有一个。例如,上面的数组将变成:

[1, 4, 2, 6, 24, 15, 60]

请注意,删除了2、6和15的重复项,以确保每个相同的元素中只有一个。Swift是否提供了一种容易做到这一点的方法,还是我必须自己做?


当前回答

为此,我做了一个尽可能简单的扩展。

extension Array where Element: Equatable {

    func containsHowMany(_ elem: Element) -> Int {
        return reduce(0) { $1 == elem ? $0 + 1 : $0 }
    }

    func duplicatesRemoved() -> Array {
        return self.filter { self.containsHowMany($0) == 1 }
    }

    mutating func removeDuplicates() {
        self = self.duplicatesRemoved(()
    }
}

您可以使用duplicatesRemoved()来获取一个新数组,它的重复元素将被删除,或者使用removeduplicate()来改变自身。看到的:

let arr = [1, 1, 1, 2, 2, 3, 4, 5, 6, 6, 6, 6, 6, 7, 8]

let noDuplicates = arr.duplicatesRemoved()
print(arr) // [1, 1, 1, 2, 2, 3, 4, 5, 6, 6, 6, 6, 6, 7, 8]
print(noDuplicates) // [1, 2, 3, 4, 5, 6, 7, 8]

arr.removeDuplicates()
print(arr) // [1, 2, 3, 4, 5, 6, 7, 8]

其他回答

你可以自己卷,比如这样:

func unique<S : Sequence, T : Hashable>(source: S) -> [T] where S.Iterator.Element == T {
    var buffer = [T]()
    var added = Set<T>()
    for elem in source {
        if !added.contains(elem) {
            buffer.append(elem)
            added.insert(elem)
        }
    }
    return buffer
}

let vals = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
let uniqueVals = uniq(vals) // [1, 4, 2, 6, 24, 15, 60]

作为Array的扩展:

extension Array where Element: Hashable {
    func uniqued() -> Array {
        var buffer = Array()
        var added = Set<Element>()
        for elem in self {
            if !added.contains(elem) {
                buffer.append(elem)
                added.insert(elem)
            }
        }
        return buffer
    }
}

或者更优雅一点(Swift 4/5):

extension Sequence where Element: Hashable {
    func uniqued() -> [Element] {
        var set = Set<Element>()
        return filter { set.insert($0).inserted }
    }
}

将被使用:

[1,2,4,2,1].uniqued()  // => [1,2,4]

包含相等性检查,而插入检查哈希,最安全的检查方式如下:

extension Array where Element: Hashable {

    /// Big O(N) version. Updated since @Adrian's comment. 
    var uniques: Array {
        // Go front to back, add element to buffer if it isn't a repeat.
         var buffer: [Element] = []
         var dictionary: [Element: Int] = [:]
         for element in self where dictionary[element] == nil {
             buffer.append(element)
             dictionary[element] = 1
         }
         return buffer
    }
}

这里有一个解决方案

不使用传统NS类型 对于O(n)来说是相当快的 简洁 保持元素顺序

extension Array where Element: Hashable {

    var uniqueValues: [Element] {
        var allowed = Set(self)
        return compactMap { allowed.remove($0) }
    }
}

斯威夫特5.7

使用有序集

您可以将具有重复元素的数组传递给以下通用函数,该函数处理有序Set并返回没有重复元素的新数组。

import Foundation

internal func withoutDuplicates<T>(_ array: [T]) -> [T] {
    
    let orderedSet: NSMutableOrderedSet = []
    var modifiedArray = [T]()
    
    orderedSet.addObjects(from: array)
    
    for i in 0...(orderedSet.count - 1) {
        modifiedArray.append(orderedSet[i] as! T)
    }
    return modifiedArray
}

////////////////////////////////////////////////////////////

let arrayOfStrings: [String] = ["A","A","A","B","B","C","C"]
let arrayOfIntegers: [UInt8] = [1, 1, 1, 2, 2, 2, 3, 3]
let arrayOfBooleans: [Bool] = [true, false, false, true]

let ordered_01 = withoutDuplicates(arrayOfStrings)
let ordered_02 = withoutDuplicates(arrayOfIntegers)
let ordered_03 = withoutDuplicates(arrayOfBooleans)

结果:

// ordered_01  –––>  ["A","B","C"]
// ordered_02  –––>  [1, 2, 3]
// ordered_03  –––>  [true, false]

使用无序集

如果新数组中元素的顺序对您来说并不重要,则在处理时使用无序集。无序集中的元素类型必须符合哈希协议。

import UIKit

fileprivate func noDuplicates<T: Hashable>(_ array: [T]) -> [T] {
    
    var unorderedSet = Set<T>()
    var modifiedArray: [T] = []
    
    for i in 0...(array.count - 1) {
        unorderedSet.insert(array[i])
    }
    for i in unorderedSet.indices {
        modifiedArray.append(unorderedSet[i])
    }
    return modifiedArray
}

////////////////////////////////////////////////////////////

let arrayOfInts: [Int] = [10, 5, 7, 200, -500, 10, 7, 5]
let arrayOfStrs: [String] = ["A","A","A","B","B","C","C"]
let arrayOfBools: [Bool] = [true, false, false, true]

let unordered_01 = noDuplicates(arrayOfInts)
let unordered_02 = noDuplicates(arrayOfStrs)
let unordered_03 = noDuplicates(arrayOfBools)

结果:

// unordered_01  –––>  [200, 7, 10, -500, 5]
// unordered_02  –––>  ["B", "C", "A"]
// unordered_03  –––>  [false, true]

首先将数组的所有元素添加到NSOrderedSet中。 这将删除数组中的所有重复项。 再次将这个orderedset转换为一个数组。

做……

例子

let array = [1,1,1,1,2,2,2,2,4,6,8]

let orderedSet : NSOrderedSet = NSOrderedSet(array: array)

let arrayWithoutDuplicates : NSArray = orderedSet.array as NSArray

输出arraywithoutduplates - [1,2,4,6,8]