键路径值类型“Int”无法转换为上下文类型“String”

2024-04-23

我试图将包含 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))

现在,导致两者pageViews and sessionDuration属性是integers,这会起作用。

但是如果我想传递两个不同类型的属性(比如String and Int),我收到此错误:

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

这是其余的代码,但我猜不是那么相关:

enum OrderType: String {
    case asc
    case desc
}

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

我应该如何定义排序方法以便它接受异质的关键路径?


在 Swift 5.9 中,您可以使用参数包编写这样的方法。这里我使用内置的排序来实现KeyPathComparator:

extension Array {
    mutating func sort<each T: Comparable>(by keyPaths: repeat (KeyPath<Element, each T>, SortOrder)) {
        var comparators: [KeyPathComparator<Element>] = []
        func addComparator<Key: Comparable>(_ keyPathOrder: (KeyPath<Element, Key>, SortOrder)) {
            comparators.append(KeyPathComparator(keyPathOrder.0, order: keyPathOrder.1))
        }
        // here I am technically creating a tuple, with its elements all being addComparator calls
        // this could be written more readably when we can iterate over a parameter pack with a for loop
        (repeat addComparator(each keyPaths))
        sort(using: comparators)
    }
}

用法示例:

// order by length of string ascendingly, then by the string itself descendingly
someStrings.sort(by: (\.count, .forward), (\.self, .reverse))

在 Swift 5.9 之前,您需要编写AnyComparable类型橡皮擦。这个是根据这篇文章改编的here https://stackoverflow.com/questions/68878549/class-anycomparable-inherits-from-class-anyequatable/68878884#68878884.

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))
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

键路径值类型“Int”无法转换为上下文类型“String” 的相关文章

随机推荐

  • Flask Python 未加载 main.css

    文件结构如下 app py 和 app2 py 几乎相同 只是 app2 py 指向 templates 文件夹 因为 app2 py 位于 src 文件夹中 app py app2 py 通过 app py 加载时 一切运行正常并且找到了
  • ReferenceError:CKEDITOR 未定义

    我正在尝试使用CK编辑器 http ckeditor com 但是当我尝试时出现以下错误 在 JS 控制台中 例子 http docs ckeditor com guide dev framed从教程中 浏览器中仅显示一个文本框 Refer
  • 独立Python3脚本之间的进程间通信

    我们可以使用标准的 multiprocessing Queue 类在独立的 Python3 脚本之间进行通信吗 bash aaa py bash bbb py 如果没有 是否有另一个库 例如标准多处理模块 用于与独立脚本进行通信 看一下有关
  • Webpack 中的 /node_modules/watchpack 中出现“无法解析模块 'aws-sdk'、'child_process'、'net'”

    我正在尝试构建我的 prod webpack 文件并收到 5 10 个 无法解析模块 aws sdk child process 的错误 所有这些错误都以相同的路径开始 ERROR in webpack watchpack chokidar
  • 如何在对象字段值发生变化时定义断点?

    作为示例 给出下面的代码摘录 我想定义一个断点 每当对象字段值发生变化时就会触发断点 并且可以选择根据条件中断 False or True在这种情况下 type TForm1 class TForm EnableButton TButton
  • 一个表列可用于多个 fk 表?

    对于这种情况 最好的解决方案 做法是什么 我有一个表 可以引用多个表 对象 以下是 UserCalendar 表的示例 这是一个用户保存事件的表 但系统也从后面插入到该表中 用户执行一些有截止日期的服务 这些服务也被插入到该表中 问题是没有
  • 为什么 C# 在这种情况下无法解决正确的重载问题?

    我遇到过一种明确的奇怪情况 但重载解析器并不这么认为 考虑 public static class Program delegate int IntDel delegate string StringDel delegate void Pa
  • 是否可以在 Jenkins 的构建后操作中执行 JavaScript 脚本?

    我需要在构建结束后执行 JavaScript 脚本 该脚本应该使用 npm 包 我安装的插件是 post build actions 我发现类似带有选项的执行脚本 add generic file script 如果我在这里给出 js脚本
  • 如何在 jQuery 中删除 css 属性

    if prev clicked accordion li a category css background image url img off all channel png accordion li a comment css back
  • posix_fadvise(WILLNEED) 会使 IO 变慢吗?

    在运行 Linux 内核版本 2 6 18 194 26 1 el5 的 CentOS 5 5 机器上 我注意到 posix fadvise WILLNEED 使读取 60K 文件比常规 IO 慢了近 200 看起来实际的 fadvise
  • 关联注入还是依赖注入?

    我正在研究依赖注入模式 我看过很多例子 其中一个典型的例子就是以XxxService XxxRepository为例 但我认为 根据UML概念 类XxxRepository应该是类XxxService的关联 为什么不称这种情况为关联注入 但
  • 如何获得Arc积分?

    我正在研究核心动画和核心图形 我正在绘制一个以中心 0 0 为中心的圆弧 现在我想在圆弧之后绘制一条线 我可以绘制圆弧 但之后我无法获得两个不同的圆弧点 我怎样才能得到它 这是代码 CGMutablePathRef retPath CGPa
  • 库存管理系统的 SQL 与 NoSQL

    我正在开发一个基于 JAVA 的网络应用程序 主要目的是拥有在多个称为渠道的网站上销售的产品的库存 我们将担任所有这些渠道的管理者 我们需要的是 用于管理每个渠道的库存更新的队列 库存表 其中包含每个通道上分配的正确快照 将会话 ID 和其
  • 将字符串中的数字替换为字符串和附加到该字符串的数字的长度

    基本上我需要在数据框中取一列 其中包含字符和数字的组合 例如 XYZABC 123441 s sdx 和类似的类型 我需要删除所有标点符号 单字母单词 用单空格替换双空格 修剪字符串 并将数字替换为 NUMB 其中 表示数字的长度 所以这里
  • 循环遍历复选框并对每个选中或未选中的复选框进行计数

    我遇到了一点问题 这是一个简短的解释 我在标准表格上有 12 个复选框 我需要做的是循环遍历它们中的每一个并了解哪些已检查 哪些未检查 使用它 我可以构建一个字符串 然后将其输入到数据库字段中 这是一个例子 检查1 已检查 检查2 未检查
  • 如何在多个 Twitter Bootstrap 选项卡上只有一个表单?

    如何将多个 Twitter Bootstrap 选项卡合二为一 div class tabbable ul class nav nav tabs li class active a href 1 Tab1 a li li a href 2
  • 有人可以向我解释一下什么时候使用 MapMaker 或 WeakHashMaps 有用吗?

    我读过很多人非常喜欢MapMaker http guava libraries googlecode com svn trunk javadoc com google common collect MapMaker htmlGoogle G
  • 手势识别器和 TableView

    我有一个 UIView 覆盖了 UITableView 的所有内容 UIView 使用手势识别器来控制表格显示的内容 我仍然需要垂直 UITableView 滚动和行点击 我如何将这些从手势识别器传递到桌子上 如果您需要知道单元格的索引路径
  • 为什么使用 $PATH 以及它是什么

    我对编程有点陌生 不是真的 但我仍在学习 我们不是吗 虽然我了解 Java 和 Python 并且了解 C C JS C HTML CSS 等 并且我可以在终端中很好地导航 但我不熟悉终端中的 PATH 是什么 我使用 Linux 终端和
  • 键路径值类型“Int”无法转换为上下文类型“String”

    我试图将包含 KeyPath 和排序顺序类型的多个元组传递给应该进行排序的方法 我有这个方法 extension Array mutating func sort