Swift中数组的直方图 [英] Histogram of Array in Swift

查看:147
本文介绍了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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆