Skip to content

Instantly share code, notes, and snippets.

@LarsStegman
Last active May 13, 2021 11:15
Show Gist options
  • Save LarsStegman/a030771aed4aeffaded615f8b94ce8a0 to your computer and use it in GitHub Desktop.
Save LarsStegman/a030771aed4aeffaded615f8b94ce8a0 to your computer and use it in GitHub Desktop.
A Swifty sort descriptor
//
// SortDescriptor.swift
// MyTubePlayer
//
// Created by Lars Stegman on 04/12/2018.
// Copyright © 2018 Stegman. All rights reserved.
//
import Foundation
enum SortDescriptor<T> {
case composed([SortDescriptor<T>])
case singular((T, T) -> ComparisonResult, Bool)
func compare(_ lhs: T, _ rhs: T) -> ComparisonResult {
switch self {
case .composed(let descriptors):
for d in descriptors {
switch d.compare(lhs, rhs) {
case .orderedSame: continue
case let r: return r
}
}
return .orderedSame
case .singular(let c, let shouldOrderAscending):
let r = c(lhs, rhs)
return shouldOrderAscending ? r : r.inverted()
}
}
func inverted() -> SortDescriptor<T> {
switch self {
case .composed(let r): return .composed(r.reversed())
case .singular(let r, let orderAscending): return .singular(r, !orderAscending)
}
}
}
extension SortDescriptor {
static func ascending<K: Comparable>(_ keyPath: KeyPath<T, K>) -> SortDescriptor<T> {
return .singular({ (lhs, rhs) in
return lhs[keyPath: keyPath].compare(to: rhs[keyPath: keyPath])
}, true)
}
static func descending<K: Comparable>(_ keyPath: KeyPath<T, K>) -> SortDescriptor<T> {
return SortDescriptor<T>.ascending(keyPath).inverted()
}
}
extension SortDescriptor {
func orderedAscending(_ lhs: T, _ rhs: T) -> Bool {
return compare(lhs, rhs) == .orderedAscending
}
}
extension Comparable {
func compare(to: Self) -> ComparisonResult {
if self < to {
return .orderedAscending
} else if self == to {
return .orderedSame
} else {
return .orderedDescending
}
}
}
extension ComparisonResult {
func inverted() -> ComparisonResult {
switch self {
case .orderedAscending: return .orderedDescending
case .orderedDescending: return .orderedAscending
default: return self
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment