แรงบันดาลใจจากhttps://www.swiftbysundell.com/posts/the-power-of-key-paths-in-swiftเราสามารถประกาศเครื่องมือที่มีประสิทธิภาพยิ่งขึ้นที่สามารถกรองความเป็นอันหนึ่งอันเดียวกันบน keyPath ใด ๆ ขอบคุณที่ Alexander แสดงความคิดเห็นเกี่ยวกับคำตอบที่หลากหลายเกี่ยวกับความซับซ้อนโซลูชันด้านล่างควรใกล้เคียงที่สุด
วิธีการไม่กลายพันธุ์
เราขยายฟังก์ชั่นที่สามารถกรองความเป็นอันหนึ่งอันเดียวกันบน keyPath ใด ๆ :
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 }
}
}
หมายเหตุ: ในกรณีที่วัตถุของคุณไม่สอดคล้องกับ RangeReplaceableCollection แต่ไม่สอดคล้องกับ Sequence คุณสามารถมีส่วนขยายเพิ่มเติมนี้ได้ แต่ประเภทส่งคืนจะเป็น 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 }
}
}
การใช้
หากเราต้องการความเป็นเอกภาพสำหรับองค์ประกอบด้วยตนเองเช่นเดียวกับคำถามเราใช้ 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] */
ถ้าเราต้องการความเป็นหนึ่งเดียวกับสิ่งอื่น (เช่นid
ชุดของวัตถุ) เราใช้ keyPath ที่เราเลือก:
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}] */
วิธีการกลายพันธุ์
เราขยายด้วยฟังก์ชันการกลายพันธุ์ที่สามารถกรองความเป็นเอกภาพใน keyPath ใด ๆ :
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 }
}
}
การใช้
หากเราต้องการความเป็นเอกภาพสำหรับองค์ประกอบด้วยตนเองเช่นเดียวกับคำถามเราใช้ 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] */
ถ้าเราต้องการความเป็นหนึ่งเดียวกับสิ่งอื่น (เช่นid
ชุดของวัตถุ) เราใช้ keyPath ที่เราเลือก:
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 คือชุดของวัตถุที่ไม่เรียงลำดับหากจำเป็นต้องเรียงลำดับ NSOrderedSet