Impressed by https://www.swiftbysundell.com/posts/the-power-of-key-paths-in-swift, we are able to declare a extra highly effective instrument that is ready to filter for unicity on any keyPath. Because of Alexander feedback on varied solutions relating to complexity, the under options must be close to optimum.
Non-mutating answer
We prolong with a perform that is ready to filter for unicity on any keyPath:
extension RangeReplaceableCollection {
/// Returns a set containing, so as, the primary cases of
/// parts of the sequence that examine equally for the keyPath.
func distinctive<T: Hashable>(for keyPath: KeyPath<Aspect, T>) -> Self {
var distinctive = Set<T>()
return filter { distinctive.insert($0[keyPath: keyPath]).inserted }
}
}
Word: within the case the place your object would not conform to RangeReplaceableCollection, however does conform to Sequence, you’ll be able to have this extra extension, however the return kind will all the time be an Array:
extension Sequence {
/// Returns an array containing, so as, the primary cases of
/// parts of the sequence that examine equally for the keyPath.
func distinctive<T: Hashable>(for keyPath: KeyPath<Aspect, T>) -> [Element] {
var distinctive = Set<T>()
return filter { distinctive.insert($0[keyPath: keyPath]).inserted }
}
}
Utilization
If we would like unicity for parts themselves, as within the query, we use the keyPath .self
:
let a = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
let b = a.distinctive(for: .self)
/* b is [1, 4, 2, 6, 24, 15, 60] */
If we would like unicity for one thing else (like for the id
of a set of objects) then we use the keyPath of our selection:
let a = [CGPoint(x: 1, y: 1), CGPoint(x: 2, y: 1), CGPoint(x: 1, y: 2)]
let b = a.distinctive(for: .y)
/* b is [{x 1 y 1}, {x 1 y 2}] */
Mutating answer
We prolong with a mutating perform that is ready to filter for unicity on any keyPath:
extension RangeReplaceableCollection {
/// Retains solely, so as, the primary cases of
/// parts of the gathering that examine equally for the keyPath.
mutating func uniqueInPlace<T: Hashable>(for keyPath: KeyPath<Aspect, T>) {
var distinctive = Set<T>()
removeAll { !distinctive.insert($0[keyPath: keyPath]).inserted }
}
}
Utilization
If we would like unicity for parts themselves, as within the query, we use the keyPath .self
:
var a = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
a.uniqueInPlace(for: .self)
/* a is [1, 4, 2, 6, 24, 15, 60] */
If we would like unicity for one thing else (like for the id
of a set of objects) then we use the keyPath of our selection:
var a = [CGPoint(x: 1, y: 1), CGPoint(x: 2, y: 1), CGPoint(x: 1, y: 2)]
a.uniqueInPlace(for: .y)
/* a is [{x 1 y 1}, {x 1 y 2}] */