值可相等的字典序列的扩展

Extension for sequences of dictionaries where the values are Equatable

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

Binary operator == cannot be applied to two 'Equatable' operands

这些显然是等同的且类型相同 (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
    }
}

A [String: Equatable] 是字符串到 any Equatable 类型的映射。不保证每个值都是 same 可等值类型。也就是说,实际上不可能创建这样的字典(因为 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([=10=], item) }) {
                noDoubles.append(item)
            }
        }
        return noDoubles
    }
}

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

这与您的代码在缺少 name 时的行为方式略有不同,但稍作调整就可以获得您想要的结果。

也就是说,对此的需求强烈表明数据模型不正确。如果你有这个字典序列,并且你正试图在它的基础上构建一个扩展,你几乎肯定想要有一个结构序列。那么这就变得更直接了。字典的要点是键到值的任意映射。如果您有一小组合法的已知密钥,那确实是一个结构。