Swift中数组的直方图 [英] Histogram of Array in Swift
问题描述
我正在尝试编写一个在Array
上运行的通用直方图函数,但是由于类型'Element'不符合协议'Hashable',我遇到了麻烦./p>
I'm trying to write a generic histogram function that operates on an Array
, but I'm running into difficulties as Type 'Element' does not conform to protocol 'Hashable'.
extension Array {
func histogram() -> [Array.Element: Int] {
return self.reduce([Array.Element: Int]()) { (acc, key) in
let value = (acc[key] == nil) ? 1 : (acc[key]! + 1)
return acc.dictionaryByUpdatingKey(key: key, value: value)
}
}
}
其中dictionaryByUpdatingKey(...)
如下修改现有字典:
where dictionaryByUpdatingKey(...)
mutates an existing dictionary as follows:
extension Dictionary {
func dictionaryByUpdatingKey(key: Dictionary.Key, value: Dictionary.Value) -> Dictionary {
var mutableSelf = self
let _ = mutableSelf.updateValue(value, forKey: key)
return mutableSelf
}
}
我尝试用AnyHashable
替换Array.Element
,然后强制使用key as! AnyHashable
,但这似乎很混乱,并且返回类型最好与Array.Element
具有相同的类型,而不是AnyHashable
.
I have tried replacing Array.Element
with AnyHashable
and then forcing the key as! AnyHashable
, but this seems messy and the return type should preferably be of the same type as the Array.Element
and not of AnyHashable
.
我希望使用Array
扩展名,如下所示:
I wish to use the Array
extension as follows:
let names = ["Alex", "Alex", "James"]
print(names.histogram()) // ["James": 1, "Alex": 2]
或
let numbers = [2.0, 2.0, 3.0]
print(numbers.histogram()) // [3.0: 1, 2.0: 2]
推荐答案
在扩展名中添加通用where子句:where Element: Hashable
:
extension Sequence where Element: Hashable {
func histogram() -> [Element: Int] {
return self.reduce([Element: Int]()) { (acc, key) in
let value = acc[key, default: 0] + 1
return acc.dictionaryByUpdatingKey(key: key, value: value)
}
}
}
我还结合了@MartinR的建议,即使用新的default
值进行字典查找.
I also incorporated @MartinR's suggestion of using the new default
value for dictionary look ups.
使用 reduce(into:_:)
,您可以更轻松地完成此操作高效地
Using reduce(into:_:)
you can do this much more simply and efficiently:
extension Sequence where Element: Hashable {
func histogram() -> [Element: Int] {
return self.reduce(into: [:]) { counts, elem in counts[elem, default: 0] += 1 }
}
}
这篇关于Swift中数组的直方图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!