Https://www.swiftbysundell.com/posts/the-power-of-key-paths-in-swift से प्रेरित होकर , हम एक और अधिक शक्तिशाली उपकरण की घोषणा कर सकते हैं जो किसी भी कीपथ पर एकता के लिए फ़िल्टर करने में सक्षम है। जटिलता के संबंध में विभिन्न उत्तरों पर अलेक्जेंडर की टिप्पणियों के लिए धन्यवाद, नीचे के समाधान इष्टतम के पास होने चाहिए।
गैर-उत्परिवर्ती समाधान
हम एक ऐसे फ़ंक्शन के साथ विस्तार करते हैं जो किसी भी 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 के अनुरूप नहीं है, लेकिन अनुक्रम के अनुरूप है, आपके पास यह अतिरिक्त एक्सटेंशन हो सकता है, लेकिन रिटर्न प्रकार हमेशा एक सरणी होगा:
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
वस्तुओं के संग्रह के लिए) तो हम अपनी पसंद के कीथ का उपयोग करते हैं:
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
वस्तुओं के संग्रह के लिए) तो हम अपनी पसंद के कीथ का उपयोग करते हैं:
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
, एनएसएसटेट वस्तुओं का एक अनियंत्रित संग्रह है, अगर ऑर्डर एनएसओडरडसेट रखने की आवश्यकता है।