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

[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]

其他回答

在Swift 5中

 var array: [String] =  ["Aman", "Sumit", "Aman", "Sumit", "Mohan", "Mohan", "Amit"]

 let uniq = Array(Set(array))
 print(uniq)

输出将是

 ["Sumit", "Mohan", "Amit", "Aman"]

下面是使用自定义匹配函数使序列唯一的更灵活的方法。

extension Sequence where Iterator.Element: Hashable {

    func unique(matching: (Iterator.Element, Iterator.Element) -> Bool) -> [Iterator.Element] {

        var uniqueArray: [Iterator.Element] = []
        forEach { element in
            let isUnique = uniqueArray.reduce(true, { (result, item) -> Bool in
                return result && matching(element, item)
            })
            if isUnique {
                uniqueArray.append(element)
            }
        }
        return uniqueArray
    }
}

使用Set或NSOrderedSet删除重复项,然后转换回数组:

let uniqueUnordered = Array(Set(array))
let uniqueOrdered = Array(NSOrderedSet(array: array))

我相信提供一个uniq()和uniqInPlace()函数通过删除数组的值来改变数组是很好的。这类似于Swift提供的sort()和sortInPlace()函数。此外,由于它是一个数组,它应该保持它的原始元素顺序。

extension Array where Element: Equatable {

    public func uniq() -> [Element] {
        var arrayCopy = self
        arrayCopy.uniqInPlace()
        return arrayCopy
    }

    mutating public func uniqInPlace() {
        var seen = [Element]()
        var index = 0
        for element in self {
            if seen.contains(element) {
                removeAtIndex(index)
            } else {
                seen.append(element)
                index++
            }
        }
    }
}

你只能在变量数组(即var)上使用uniqInPlace(),因为你不能改变常量数组(即let)。

一些用法示例:

var numbers = [1, 6, 2, 2, 4, 1, 5]
numbers.uniqInPlace() // array is now [1, 6, 2, 4, 5]

let strings = ["Y", "Z", "A", "Y", "B", "Y", "Z"]
let uniqStrings = strings.uniq() // uniqStrings is now ["Y", "Z", "A", "B"]

这里有很多答案,但我错过了这个简单的扩展,适合Swift 2及以上:

extension Array where Element:Equatable {
    func removeDuplicates() -> [Element] {
        var result = [Element]()

        for value in self {
            if result.contains(value) == false {
                result.append(value)
            }
        }

        return result
    }
}

这非常简单。可以这样调用:

let arrayOfInts = [2, 2, 4, 4]
print(arrayOfInts.removeDuplicates()) // Prints: [2, 4]

基于属性的过滤

要根据属性筛选数组,你可以使用这个方法:

extension Array {

    func filterDuplicates(@noescape includeElement: (lhs:Element, rhs:Element) -> Bool) -> [Element]{
        var results = [Element]()

        forEach { (element) in
            let existingElements = results.filter {
                return includeElement(lhs: element, rhs: $0)
            }
            if existingElements.count == 0 {
                results.append(element)
            }
        }

        return results
    }
}

你可以这样调用它:

let filteredElements = myElements.filterDuplicates { $0.PropertyOne == $1.PropertyOne && $0.PropertyTwo == $1.PropertyTwo }