कई मानदंडों की तुलना करने के लिए टुपल्स का उपयोग करना
कई मानदंडों द्वारा एक प्रकार का प्रदर्शन करने का वास्तव में सरल तरीका है (अर्थात एक तुलना द्वारा क्रमबद्ध करना, और यदि समकक्ष, तो दूसरी तुलना द्वारा) का उपयोग ट्यूपल्स द्वारा किया जाता है , क्योंकि ऑपरेटर <
और >
उनके लिए अधिभार हैं जो लेक्सिकोग्राफ़िक तुलना करते हैं।
public func < <A : Comparable, B : Comparable>(lhs: (A, B), rhs: (A, B)) -> Bool
उदाहरण के लिए:
struct Contact {
var firstName: String
var lastName: String
}
var contacts = [
Contact(firstName: "Leonard", lastName: "Charleson"),
Contact(firstName: "Michael", lastName: "Webb"),
Contact(firstName: "Charles", lastName: "Alexson"),
Contact(firstName: "Michael", lastName: "Elexson"),
Contact(firstName: "Alex", lastName: "Elexson"),
]
contacts.sort {
($0.lastName, $0.firstName) <
($1.lastName, $1.firstName)
}
print(contacts)
यह lastName
पहले तत्वों के गुणों की तुलना करेगा । यदि वे समान नहीं हैं, तो <
उनके साथ तुलना के आधार पर क्रम क्रम आधारित होगा । वे तो हैं बराबर है, तो यह टपल में तत्वों की अगले जोड़ी पर ले जाते हैं, की तुलना यानी जाएगा firstName
गुण।
मानक पुस्तकालय 2 से 6 तत्वों के टुपल्स के लिए प्रदान करता है <
और >
ओवरलोड करता है ।
यदि आप अलग-अलग गुणों के लिए अलग-अलग सॉर्टिंग ऑर्डर चाहते हैं, तो आप टुपल्स में तत्वों को स्वैप कर सकते हैं:
contacts.sort {
($1.lastName, $0.firstName) <
($0.lastName, $1.firstName)
}
यह अब lastName
अवरोही, फिर firstName
आरोही द्वारा क्रमबद्ध होगा ।
एक sort(by:)
अधिभार को परिभाषित करना जो कई विधेय लेता है
क्लोजर और SortDescriptors के साथ सॉर्टिंग कलेक्शंसmap
पर चर्चा से प्रेरित , एक अन्य विकल्प एक कस्टम अधिभार को परिभाषित करना होगा sort(by:)
और sorted(by:)
जो कई विधेयकों से संबंधित होता है - जहां तत्वों के क्रम को तय करने के लिए प्रत्येक विधेय को बारी-बारी से माना जाता है।
extension MutableCollection where Self : RandomAccessCollection {
mutating func sort(
by firstPredicate: (Element, Element) -> Bool,
_ secondPredicate: (Element, Element) -> Bool,
_ otherPredicates: ((Element, Element) -> Bool)...
) {
sort(by:) { lhs, rhs in
if firstPredicate(lhs, rhs) { return true }
if firstPredicate(rhs, lhs) { return false }
if secondPredicate(lhs, rhs) { return true }
if secondPredicate(rhs, lhs) { return false }
for predicate in otherPredicates {
if predicate(lhs, rhs) { return true }
if predicate(rhs, lhs) { return false }
}
return false
}
}
}
extension Sequence {
mutating func sorted(
by firstPredicate: (Element, Element) -> Bool,
_ secondPredicate: (Element, Element) -> Bool,
_ otherPredicates: ((Element, Element) -> Bool)...
) -> [Element] {
return sorted(by:) { lhs, rhs in
if firstPredicate(lhs, rhs) { return true }
if firstPredicate(rhs, lhs) { return false }
if secondPredicate(lhs, rhs) { return true }
if secondPredicate(rhs, lhs) { return false }
for predicate in otherPredicates {
if predicate(lhs, rhs) { return true }
if predicate(rhs, lhs) { return false }
}
return false
}
}
}
( secondPredicate:
पैरामीटर दुर्भाग्यपूर्ण है, लेकिन मौजूदा sort(by:)
अधिभार के साथ अस्पष्टता पैदा करने से बचने के लिए आवश्यक है )
यह तब हमें कहने की अनुमति देता है ( contacts
पहले से सरणी का उपयोग करके ):
contacts.sort(by:
{ $0.lastName > $1.lastName },
{ $0.firstName < $1.firstName }
)
print(contacts)
let sortedContacts = contacts.sorted(by:
{ $0.lastName > $1.lastName },
{ $0.firstName < $1.firstName }
)
यद्यपि कॉल-साइट टपल संस्करण के रूप में संक्षिप्त नहीं है, आप इसकी तुलना किस क्रम और किस क्रम में कर रहे हैं, के साथ अतिरिक्त स्पष्टता प्राप्त करते हैं।
के अनुरूप करना Comparable
यदि आप इस प्रकार की तुलना नियमित रूप से करने जा रहे हैं, तो @AMomchilov & @appzYourLife के अनुसार , आप इसके अनुरूप Contact
हो सकते हैं Comparable
:
extension Contact : Comparable {
static func == (lhs: Contact, rhs: Contact) -> Bool {
return (lhs.firstName, lhs.lastName) ==
(rhs.firstName, rhs.lastName)
}
static func < (lhs: Contact, rhs: Contact) -> Bool {
return (lhs.lastName, lhs.firstName) <
(rhs.lastName, rhs.firstName)
}
}
और अब बस sort()
आरोही क्रम के लिए कॉल करें :
contacts.sort()
या sort(by: >)
एक अवरोही क्रम के लिए:
contacts.sort(by: >)
नेस्टेड प्रकार में कस्टम प्रकार के आदेशों को परिभाषित करना
यदि आपके पास अन्य प्रकार के आदेश हैं जिनका आप उपयोग करना चाहते हैं, तो आप उन्हें एक नेस्टेड प्रकार में परिभाषित कर सकते हैं:
extension Contact {
enum Comparison {
static let firstLastAscending: (Contact, Contact) -> Bool = {
return ($0.firstName, $0.lastName) <
($1.firstName, $1.lastName)
}
}
}
और फिर बस के रूप में कॉल करें:
contacts.sort(by: Contact.Comparison.firstLastAscending)