簡體   English   中英

鍵路徑值類型“Int”無法轉換為上下文類型“String”

[英]Key path value type 'Int' cannot be converted to contextual type 'String'

我正在嘗試將包含 KeyPath 和排序順序類型的多個元組傳遞給應該進行排序的方法。

我有這個方法:

extension Array {
    mutating func sort<T: Comparable>(by criteria: (path: KeyPath<Element, T>, order:OrderType)...) {
        
        criteria.forEach { path, order in
            //...
            sort { first, second in
            order.makeComparator()(
                first[keyPath: path],
                second[keyPath: path]
            )
        }
        }
    }
}

我正在這樣使用它:

var posts = BlogPost.examples
        
posts.sort(by:(path:\.pageViews, order: .asc), (path:\.sessionDuration, order: .desc))

現在,由於pageViewssessionDuration屬性都是integers ,這將起作用。

但是如果我想傳遞兩個不同類型的屬性(比如StringInt ),我會收到這個錯誤:

Key path value type 'Int' cannot be converted to contextual type 'String'

這是代碼的 rest ,但我想不是那么相關:

enum OrderType: String {
    case asc
    case desc
}

extension OrderType {
    func makeComparator<T: Comparable>() -> (T, T) -> Bool {
        switch self {
        case .asc:
            return (<)
        case .desc:
            return (>)
        }
    }
}

我應該如何定義排序方法以便它接受異構鍵路徑?

沒有可變參數 generics(還),所以你需要寫一個AnyComparable類型的橡皮擦。 這個改編自這里的這篇文章。

struct AnyComparable: Equatable, Comparable {
    private let lessThan: (Any) -> Bool
    private let value: Any
    private let equals: (Any) -> Bool

    public static func == (lhs: AnyComparable, rhs: AnyComparable) -> Bool {
        lhs.equals(rhs.value) || rhs.equals(lhs.value)
    }
    
    public init<C: Comparable>(_ value: C) {
        self.value = value
        self.equals = { $0 as? C == value }
        self.lessThan = { ($0 as? C).map { value < $0 } ?? false }
    }

    public static func < (lhs: AnyComparable, rhs: AnyComparable) -> Bool {
        lhs.lessThan(rhs.value) || (rhs != lhs && !rhs.lessThan(lhs.value))
    }
}

這樣,您可以將sort方法簽名編寫為:

mutating func sort(by criteria: (path: KeyPath<Element, AnyComparable>, order:OrderType)...) {
    
    
}

為了讓我們更容易傳遞AnyComparable類型的關鍵路徑,我們可以做一個擴展:

extension Comparable {
    // this name might be too long, but I'm sure you can come up with a better name
    var anyComparable: AnyComparable {
        .init(self)
    }
}

現在我們可以這樣做:

someArray.sort(by: (\.key1.anyComparable, .asc), (\.key2.anyComparable, .asc))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM