0

我尝试实现以下方法,通过比较字典数组的特定键来删除字典数组中的双重条目。但是,由于以下错误,此扩展方法将不起作用:

二元运算符 == 不能应用于两个 'Equatable' 操作数

这些显然是等价的并且类型相同(Iterator.Element.Value),那么为什么它不起作用呢?

我看到它将 Equatable 视为特定类型,而不是约束。我无法使其适用于泛型类型或编写where Iterator.Element == [String: Any], Iterator.Element.Value: Equatable.

你们有任何关于如何解决这个问题的线索吗?

extension Sequence where Iterator.Element == [String: Equatable] {
    public func removeDoubles(byKey uniqueKey: String) -> [Iterator.Element] {
        var uniqueValues: [Iterator.Element.Value] = []
        var noDoubles: [Iterator.Element] = []
        for item in self {
            if let itemValue = item[uniqueKey] {
                if (uniqueValues.contains { element in
                    return itemValue == element
                }) {
                    uniqueValues.append(itemValue)
                    noDoubles.append(item)
                }
            }
        }
        return noDoubles
    }
}
4

1 回答 1

0

A[String: Equatable]是字符串到任何Equatable 类型的映射。没有保证每个值都是相同的等价类型。也就是说,实际上不可能创建这样的字典(因为Equatable有关联的类型),所以这个扩展不能应用于 Swift 中的任何实际类型。(您在这里没有收到错误的事实是 IMO 编译器中的一个错误。)

完成这项工作所需的功能是SE-0142,它已被接受,但未实现。您目前无法通过这种方式基于类型约束来约束扩展。

有很多方法可以实现您想要做的事情。一种直接的方法是传递你的相等函数:

extension Sequence {
    public func removeDoubles(with equal: (Iterator.Element, Iterator.Element) -> Bool) -> [Iterator.Element] {
        var noDoubles: [Iterator.Element] = []
        for item in self {
            if !noDoubles.contains(where: { equal($0, item) }) {
                noDoubles.append(item)
            }
        }
        return noDoubles
    }
}

let noDupes = dict.removeDoubles(with: { $0["name"] == $1["name"] })

这与您的代码在丢失时的行为方式略有不同name,但轻微的调整可以得到您想要的。

也就是说,对此的需求强烈表明数据模型不正确。如果您有这个字典序列,并且您正在尝试在其上构建一个扩展,那么您几乎肯定意味着有一个结构序列。然后这变得更加简单。字典的要点是键到值的任意映射。如果您有一小组合法的已知键,那确实是一个结构。

于 2017-02-27T15:49:15.457 回答