Generic function to sort array of class by properties

前端 未结 3 747
我在风中等你
我在风中等你 2020-12-02 01:15

I want to create a generic function to sort an array of classes based on a property passed.

For example, I have these classes

public class Car {
             


        
3条回答
  •  北荒
    北荒 (楼主)
    2020-12-02 01:30

    Expanding on @MartinR answer to allow increasing (<) or decreasing (>) sort:


    extension MutableCollection where Self: RandomAccessCollection {
        mutating func sort(_ keyPath: KeyPath, by areInIncreasingOrder: ((T, T) -> Bool) = (<)) {
            sort(by: { areInIncreasingOrder($0[keyPath: keyPath], $1[keyPath: keyPath]) })
        }
    }
    

    extension Sequence {
        func sorted(_ keyPath: KeyPath, by areInIncreasingOrder: ((T,T)-> Bool) = (<)) -> [Element] {
            sorted(by: { areInIncreasingOrder($0[keyPath: keyPath], $1[keyPath: keyPath]) })
        }
    }
    

    people.sorted(\.age)
    people.sorted(\.age, by: >)
    
    cars.sorted(\.manufacturer)
    cars.sorted(\.manufacturer, by: >)
    

    edit/update:

    To suport sorting a custom object by an optional property that conforms to Comparable protocol:


    extension MutableCollection where Self: RandomAccessCollection {
        mutating func sort(_ keyPath: KeyPath>, by areInIncreasingOrder: ((T, T) -> Bool) = (<)) {
            sort(by: {
                switch ($0[keyPath: keyPath], $1[keyPath: keyPath]) {
                case let (lhs?, rhs?): return areInIncreasingOrder(lhs, rhs)
                case (.none, _): return false
                case (_, .none): return true
                }
            })
        }
    }
    

    extension Sequence {
        func sorted(_ keyPath: KeyPath>, by areInIncreasingOrder: ((T,T)-> Bool) = (<)) -> [Element]  {
            sorted(by: {
                switch ($0[keyPath: keyPath], $1[keyPath: keyPath]) {
                case let (lhs?, rhs?): return areInIncreasingOrder(lhs, rhs)
                case (.none, _): return false
                case (_, .none): return true
                }
            })
        }
    }
    

    Usage:

    array.sort(\.optionalStringProperty) {
        $0.localizedStandardCompare($1) == .orderedAscending
    }
    print(array)
    

提交回复
热议问题