Https://www.swiftbysundell.com/posts/the-power-of-key-paths-in-swift'ten esinlenerek , herhangi bir keyPath üzerindeki tekliği filtreleyebilen daha güçlü bir araç bildirebiliriz. Alexander'ın karmaşıklıkla ilgili çeşitli cevaplar hakkındaki yorumları sayesinde, aşağıdaki çözümler optimal olmalıdır.
Değişmeyen çözelti
Herhangi bir keyPath üzerinde tekliği filtreleyebilen bir işlevle genişletiyoruz:
extension RangeReplaceableCollection {
/// Returns a collection containing, in order, the first instances of
/// elements of the sequence that compare equally for the keyPath.
func unique<T: Hashable>(for keyPath: KeyPath<Element, T>) -> Self {
var unique = Set<T>()
return filter { unique.insert($0[keyPath: keyPath]).inserted }
}
}
Not: nesnenizin RangeReplaceableCollection ile uyumlu olmadığı, ancak Sekans ile uyumlu olduğu durumda, bu ek uzantıya sahip olabilirsiniz, ancak dönüş türü her zaman bir Array olur:
extension Sequence {
/// Returns an array containing, in order, the first instances of
/// elements of the sequence that compare equally for the keyPath.
func unique<T: Hashable>(for keyPath: KeyPath<Element, T>) -> [Element] {
var unique = Set<T>()
return filter { unique.insert($0[keyPath: keyPath]).inserted }
}
}
kullanım
Soruda olduğu gibi, elemanların kendileri için teklik istiyorsak, keyPath'i kullanırız \.self
:
let a = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
let b = a.unique(for: \.self)
/* b is [1, 4, 2, 6, 24, 15, 60] */
Başka bir şey için teklik istiyorsak id
(bir nesne koleksiyonunda olduğu gibi), seçtiğimiz keyPath'i kullanırız:
let a = [CGPoint(x: 1, y: 1), CGPoint(x: 2, y: 1), CGPoint(x: 1, y: 2)]
let b = a.unique(for: \.y)
/* b is [{x 1 y 1}, {x 1 y 2}] */
Mutasyon çözümü
Herhangi bir keyPath üzerinde tekliği filtreleyebilen bir mutasyon işlevi ile uzanırız:
extension RangeReplaceableCollection {
/// Keeps only, in order, the first instances of
/// elements of the collection that compare equally for the keyPath.
mutating func uniqueInPlace<T: Hashable>(for keyPath: KeyPath<Element, T>) {
var unique = Set<T>()
removeAll { !unique.insert($0[keyPath: keyPath]).inserted }
}
}
kullanım
Soruda olduğu gibi, elemanların kendileri için teklik istiyorsak, keyPath'i kullanırız \.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] */
Başka bir şey için teklik istiyorsak id
(bir nesne koleksiyonunda olduğu gibi), seçtiğimiz keyPath'i kullanırız:
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}] */
NSSet
NSSet sipariş NSOrderedSet tutmak gerekiyorsa, sırasız bir nesne koleksiyonudur.