I might have an array that looks like the following:
[1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
Or, reall
An alternate (if not optimal) solution from here using immutable types rather than variables:
func deleteDuplicates<S: ExtensibleCollectionType where S.Generator.Element: Equatable>(seq:S)-> S {
let s = reduce(seq, S()){
ac, x in contains(ac,x) ? ac : ac + [x]
}
return s
}
Included to contrast Jean-Pillippe's imperative approach with a functional approach.
As a bonus this function works with strings as well as arrays!
Edit: This answer was written in 2014 for Swift 1.0 (before Set
was available in Swift). It doesn't require Hashable conformance & runs in quadratic time.
Swift 4.x:
extension Sequence where Iterator.Element: Hashable {
func unique() -> [Iterator.Element] {
return Array(Set<Iterator.Element>(self))
}
func uniqueOrdered() -> [Iterator.Element] {
return reduce([Iterator.Element]()) { $0.contains($1) ? $0 : $0 + [$1] }
}
}
usage:
["Ljubljana", "London", "Los Angeles", "Ljubljana"].unique()
or
["Ljubljana", "London", "Los Angeles", "Ljubljana"].uniqueOrdered()
Done....
Example
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
output of arrayWithoutDuplicates - [1,2,4,6,8]
You can convert to a Set
and back to an Array
again quite easily:
let unique = Array(Set(originals))
This is not guaranteed to maintain the original order of the array.
Many answers available here, but I missed this simple extension, suitable for Swift 2 and up:
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
}
}
Makes it super simple. Can be called like this:
let arrayOfInts = [2, 2, 4, 4]
print(arrayOfInts.removeDuplicates()) // Prints: [2, 4]
Filtering based on properties
To filter an array based on properties, you can use this method:
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
}
}
Which you can call as followed:
let filteredElements = myElements.filterDuplicates { $0.PropertyOne == $1.PropertyOne && $0.PropertyTwo == $1.PropertyTwo }
with uniq function answer:
func uniq<S: SequenceType, E: Hashable where E==S.Generator.Element>(source: S) -> [E] {
var seen: [E:Bool] = [:]
return source.filter({ (v) -> Bool in
return seen.updateValue(true, forKey: v) == nil
})
}
use:
var test = [1,2,3,4,5,6,7,8,9,9,9,9,9,9]
print(uniq(test)) //1,2,3,4,5,6,7,8,9