튜플을 사용하여 여러 기준 비교
여러 기준에 의해 정렬을 수행하는 정말 간단한 방법 (하나 개의 비교에 의해 즉, 정렬, 다른 비교하여 다음과 경우에 해당)을 사용하는 것입니다 튜플 은 AS, <
그리고 >
운영자가 사전 식 비교를 수행 그들에게 과부하가 있습니다.
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:)
여러 술어를 사용 하는 오버로드 정의
에 대한 논의에서 영감 과 정렬 컬렉션 map
폐쇄 및 SortDescriptors , 또 다른 옵션은 사용자 지정 과부하 정의하는 것입니다 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)