值是 Equatable 的字典序列的扩展
Posted
技术标签:
【中文标题】值是 Equatable 的字典序列的扩展【英文标题】:Extension for sequences of dictionaries where the values are Equatable 【发布时间】:2017-02-27 15:14:18 【问题描述】:我尝试实现以下方法,通过比较字典数组的特定键来删除字典数组中的双重条目。但是,由于错误,此扩展方法将不起作用:
二元运算符 == 不能应用于两个 '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
【问题讨论】:
【参考方案1】:[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($0, item) )
noDoubles.append(item)
return noDoubles
let noDupes = dict.removeDoubles(with: $0["name"] == $1["name"] )
这与您的代码在缺少name
时的行为方式略有不同,但稍作调整可能会得到您想要的。
也就是说,对此的需求强烈表明数据模型不正确。如果您有这个字典序列,并且您正在尝试在其上构建一个扩展,那么您几乎肯定意味着有一个结构序列。然后这变得更加简单。字典的要点是键到值的任意映射。如果你有一小组已知的合法键,那就是一个结构体。
【讨论】:
不确定 SE-0142 在这里有什么帮助,我想你的意思是 Parameterized extensions? :) 我的意思是参数化扩展,但我认为 SE-0142 提供了这一点。可能误读了 142。 感谢您的帮助。问题是这些都是 JSON,我需要合并其中的两个 - 一个本地的和一个来自服务器的远程的。合并后它被保存到核心数据中,创建另一个结构类型似乎需要做太多的工作,因为这些是 NSManagedObjects,所以在插入它们之前我不能使用它们。在内存上下文中,将它们全部存储并比较对于这个简单的目的来说似乎太多了,所以我继续尝试这个扩展。以上是关于值是 Equatable 的字典序列的扩展的主要内容,如果未能解决你的问题,请参考以下文章