我需要在一系列 swift 字典中找到最常用的字典。我尝试使用以下内容:
func frequencies
<S: SequenceType where S.Generator.Element: Hashable>
(source: S) -> [(S.Generator.Element,Int)] {
var frequency: [S.Generator.Element:Int] = [:]
for x in source {
frequency[x] = (frequency[x] ?? 0) + 1
}
return sorted(frequency) { $0.1 > $1.1 }
}
但我无法使用 [[String:String]]()
类型的参数列表调用“频率”。我如何编辑上述函数以获取字典数组,或完全使用另一种方法?
最佳答案
正如评论所提到的,问题在于类型[String:String]
不是Hashable
。
当您的类型不可哈希时,一个(非常)低效的解决方案是回退到 Comparable
(可以排序并生成运行总计)或 Equatable
或者,最坏的情况,要求调用者提供一个 isEquivalent
闭包。然后,您将搜索运行频率以寻找等效项(如果找不到,则以频率 1 插入)。
这是在 Swift 2.0 中执行此操作的实现:
extension SequenceType {
func frequencies(@noescape isEquivalent: (Generator.Element,Generator.Element) -> Bool) -> [(Generator.Element,Int)] {
var frequency: [(Generator.Element,Int)] = []
for x in self {
// find the index of the equivalent entry
if let idx = frequency.indexOf({ isEquivalent($0.0, x)}) {
// and bump the frequency
frequency[idx].1 += 1
}
else {
// add a new entry
frequency.append(x,1)
}
}
return frequency.sort { $0.1 > $1.1 }
}
}
因为 ==
有一个比较两个字典的实现,只要那些字典包含相等的值,你就可以这样调用它:
let dicts = [
["name": "David", "number": "1"],
["name": "John", "number": "2"],
["name": "David", "number": "1"],
]
// you can use `==` in two dictionaries that contain an equatable value,
// such as String here:
dicts[0] == dicts[1] // false
dicts[0] == dicts[2] // true
// so you can call frequencies like so:
dicts.frequencies(==)
返回:
[(["number": "1", "name": "David"], 2),
(["number": "2", "name": "John"], 1)]
编辑:这是一个 Swift 1.2 版本,不幸的是,由于 1.2 中缺少带有谓词的 find
版本(在 2.0 中重命名为 indexOf
)而变得复杂。这应该可以工作,但我在这台机器上没有 1.2 的工作副本,因此您可能需要修复任何语法错误:
extension Array {
// add missing indexOf to Array as 1.2 doesn't have an equivalent
func indexOf(@noescape predicate: T->Bool) -> Int? {
for idx in indices(self) {
if predicate(self[idx]) { return idx }
}
return nil
}
}
func frequencies<S: SequenceType>
(source: S, @noescape isEquivalent: (S.Generator.Element,S.Generator.Element) -> Bool) -> [(S.Generator.Element,Int)] {
var frequency: [(S.Generator.Element,Int)] = []
for x in source {
// find the index of the equivalent entry
if let idx = frequency.indexOf({ isEquivalent($0.0, x)}) {
// and bump the frequency
frequency[idx].1 += 1
}
else {
// add a new entry
frequency.append(x,1)
}
}
return sorted(frequency) { $0.1 > $1.1 }
}
frequencies(dicts, ==)
关于arrays - 词典数组中最常见的词典,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30945685/