Swift 5字典分类的KeysbyValue

Swift 5字典分类的KeysbyValue,swift,Swift,我需要从字典中获取按值排序的键列表 我发现这个问题很接近,但还不够好: 扩展字典{ func sortedKeysByValue(通过比较方法:(值,值)->Bool)->[键]{ 回归自我 .分类{ let(lk,lv)=0美元 出租(rk、rv)=1美元 返回比较法(lv、rv) } .地图{ 让(钥匙)=0美元 返回键 } } } 让dict=[“a”:5,“b”:3,“c”:10,“d”:7,“e”:9,“f”:5] 让结果=dict.keysSortedByValue(>) //结果可

我需要从字典中获取按值排序的键列表

我发现这个问题很接近,但还不够好:

扩展字典{
func sortedKeysByValue(通过比较方法:(值,值)->Bool)->[键]{
回归自我
.分类{
let(lk,lv)=0美元
出租(rk、rv)=1美元
返回比较法(lv、rv)
}
.地图{
让(钥匙)=0美元
返回键
}
}
}
让dict=[“a”:5,“b”:3,“c”:10,“d”:7,“e”:9,“f”:5]
让结果=dict.keysSortedByValue(>)
//结果可能是:
//[“c”、“e”、“d”、“a”、“f”、“b”]或
//[“c”、“e”、“d”、“f”、“a”、“b”]
问题是:当值相等时,它应该比较键以始终产生相同的结果。为此,我需要使用
compareMethod
不仅接受
类型,还接受
类型。我试图使方法签名使用
可比较的
协议,但得到一个编译错误:

扩展字典,其中键:可比,值:可比{
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^确保键/值类型具有可比性
func sortedKeysByValue(通过比较方法:(可比较,可比较)->Bool)->[Key]{
^^^^^^^^^^^^^^^^^^^^^出现错误(请参见下文)
回归自我
.分类{
let(lk,lv)=0美元
出租(rk、rv)=1美元
返回比较方法(lv,rv)| |(lv==rv&&compareMethod(lk,rk))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^值相等时比较键
}
.地图{
让(钥匙)=0美元
返回键
}
}
}
编译错误:
协议“Compariable”只能用作一般约束,因为它具有自身或关联的类型要求

compareMethod
应该能够处理
类型和
类型。我怎么修理它

compareMethod应该能够处理
类型和
类型

不可能声明这样的函数。您需要一个函数来比较键,另一个函数来比较值

你可以这样写:

// doesn't have to be Comparable, just conforming to Equatable is fine, as you are only using "=="
extension Dictionary where Value: Equatable {
    func sortedKeysByValue(byComparingValues compareValues: (Value, Value) -> Bool, andComparingKeys compareKeys: (Key, Key) -> Bool) -> [Key] {
    return self
        .sorted {
            let (lk, lv) = $0
            let (rk, rv) = $1
            return compareValues(lv, rv) || (lv == rv && compareKeys(lk, rk))
        }.map(\.key)
    }
}
在我看来,更好的方法是使用
(值,值)->ComparisonResult
函数,而不是
(值,值)->Bool
。这不仅允许调用者指定其自定义的相等定义,而不是始终使用“==”,而且还使该方法可用于所有类型的词典

extension Dictionary {
    func sortedKeysByValue(byComparingValues compareValues: (Value, Value) -> ComparisonResult, andComparingKeys compareKeys: (Key, Key) -> Bool) -> [Key] {
        return self
            .sorted {
                let (lk, lv) = $0
                let (rk, rv) = $1
                switch compareValues(lv, rv) {
                case .orderedAscending:
                    return false
                case .orderedDescending:
                    return true
                default:
                    return compareKeys(lk, rk)
                }
            }.map(\.key)
    }

}

当然,缺点是你不能轻易地将一个比较运算符传递给这个问题。

“我找到了一个接近这个问题的答案”Que!?你的问题是什么?谢谢你的回答<代码>??是打字错误;它应该是
&&
。单行代码应该是
compareMethod(lv,rv)| |(lv==rv&&compareMethod(lk,rk))
。我更正了帖子@李岡諭 啊,这是有道理的。我不明白你为什么认为那里可以使用
,哈哈。密钥已经符合Hashable。没有必要添加一个相等的约束。@LeoDabus哦,天哪,我真傻!我的大脑在晚上工作不好:)