Inspirándonos en https://www.swiftbysundell.com/posts/the-power-of-key-paths-in-swift , podemos declarar una herramienta más poderosa que es capaz de filtrar por unicidad en cualquier keyPath. Gracias a los comentarios de Alexander sobre varias respuestas con respecto a la complejidad, las siguientes soluciones deberían ser casi óptimas.
Solución no mutante
Extendemos con una función que puede filtrar la unicidad en cualquier keyPath:
extension RangeReplaceableCollection {
func unique<T: Hashable>(for keyPath: KeyPath<Element, T>) -> Self {
var unique = Set<T>()
return filter { unique.insert($0[keyPath: keyPath]).inserted }
}
}
Nota: en el caso de que su objeto no se ajuste a RangeReplaceableCollection, pero sí se ajuste a Sequence, puede tener esta extensión adicional, pero el tipo de retorno siempre será un Array:
extension Sequence {
func unique<T: Hashable>(for keyPath: KeyPath<Element, T>) -> [Element] {
var unique = Set<T>()
return filter { unique.insert($0[keyPath: keyPath]).inserted }
}
}
Uso
Si queremos unicidad para los elementos en sí mismos, como en la pregunta, usamos el keyPath \.self
:
let a = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
let b = a.unique(for: \.self)
Si queremos unicidad para otra cosa (como para el id
de una colección de objetos), usamos el keyPath de nuestra elección:
let a = [CGPoint(x: 1, y: 1), CGPoint(x: 2, y: 1), CGPoint(x: 1, y: 2)]
let b = a.unique(for: \.y)
Solución mutante
Extendemos con una función de mutación que puede filtrar la unicidad en cualquier keyPath:
extension RangeReplaceableCollection {
mutating func uniqueInPlace<T: Hashable>(for keyPath: KeyPath<Element, T>) {
var unique = Set<T>()
removeAll { !unique.insert($0[keyPath: keyPath]).inserted }
}
}
Uso
Si queremos unicidad para los elementos en sí mismos, como en la pregunta, usamos el keyPath \.self
:
var a = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
a.uniqueInPlace(for: \.self)
Si queremos unicidad para otra cosa (como para el id
de una colección de objetos), usamos el keyPath de nuestra elección:
var a = [CGPoint(x: 1, y: 1), CGPoint(x: 2, y: 1), CGPoint(x: 1, y: 2)]
a.uniqueInPlace(for: \.y)
NSSet
NSSet es una colección desordenada de objetos, si es necesario mantener el orden NSOrderedSet.