Lấy cảm hứng từ https://www.swiftbysundell.com/posts/the-power-of-key-paths-in-swift , chúng tôi có thể tuyên bố một công cụ mạnh hơn có thể lọc tính đơn nhất trên bất kỳ keyPath nào. Nhờ nhận xét của Alexander về các câu trả lời khác nhau về độ phức tạp, các giải pháp dưới đây sẽ gần tối ưu.
Giải pháp không đột biến
Chúng tôi mở rộng với một chức năng có thể lọc tính đơn nhất trên bất kỳ keyPath nào:
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 }
}
}
Lưu ý: trong trường hợp đối tượng của bạn không tuân thủ RangeReplacizableCollection, nhưng không tuân thủ Trình tự, bạn có thể có tiện ích mở rộng bổ sung này, nhưng kiểu trả về sẽ luôn là Mảng:
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 }
}
}
Sử dụng
Nếu chúng ta muốn duy nhất cho các thành phần, như trong câu hỏi, chúng ta sử dụng 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] */
Nếu chúng ta muốn duy nhất cho một cái gì đó khác (như cho id
một bộ sưu tập các đối tượng) thì chúng ta sử dụng keyPath theo lựa chọn của chúng ta:
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}] */
Giải pháp đột biến
Chúng tôi mở rộng với chức năng đột biến có thể lọc tính đơn nhất trên bất kỳ keyPath nào:
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 }
}
}
Sử dụng
Nếu chúng ta muốn duy nhất cho các thành phần, như trong câu hỏi, chúng ta sử dụng 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] */
Nếu chúng ta muốn duy nhất cho một cái gì đó khác (như cho id
một bộ sưu tập các đối tượng) thì chúng ta sử dụng keyPath theo lựa chọn của chúng ta:
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 là một bộ sưu tập các đối tượng không có thứ tự, nếu cần giữ trật tự NSOrderedset.