Terinspirasi oleh https://www.swiftbysundell.com/posts/the-power-of-key-paths-in-swift , kita dapat mendeklarasikan alat yang lebih kuat yang mampu memfilter unicity pada keyPath apa pun. Berkat komentar Alexander tentang berbagai jawaban mengenai kompleksitas, solusi di bawah ini harus mendekati optimal.
Solusi non-mutasi
Kami memperluas dengan fungsi yang dapat memfilter untuk unicity pada keyPath apa pun:
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 }
}
}
Catatan: dalam kasus di mana objek Anda tidak sesuai dengan RangeReplaceableCollection, tetapi tidak sesuai dengan Sequence, Anda dapat memiliki ekstensi tambahan ini, tetapi tipe pengembalian akan selalu menjadi Array:
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 }
}
}
Pemakaian
Jika kita menginginkan kesatuan untuk elemen itu sendiri, seperti dalam pertanyaan, kita menggunakan keyPath \.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] */
Jika kita menginginkan unicity untuk sesuatu yang lain (seperti untuk id
koleksi benda) maka kita menggunakan keyPath pilihan kita:
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}] */
Solusi bermutasi
Kami memperluas dengan fungsi bermutasi yang dapat memfilter untuk unicity pada keyPath apa pun:
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 }
}
}
Pemakaian
Jika kita menginginkan kesatuan untuk elemen itu sendiri, seperti dalam pertanyaan, kita menggunakan 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] */
Jika kita menginginkan unicity untuk sesuatu yang lain (seperti untuk id
koleksi benda) maka kita menggunakan keyPath pilihan kita:
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 adalah kumpulan objek yang tidak terurut, jika perlu menjaga ketertiban NSOrderedSet.