函数名称: my_counter
输入: ['foo', 'bar', 'bar', 'bar', 'bar']]
输出: {'foo': 1, 'bar': 4}
注意:输出类型是HashMap,不是HashMap<&str, usize>。
这是我的实现,我认为它有一点开销。 “bar”已被转换为字符串四次,但可能不需要。
pub fn my_counter(vec: &Vec<String>) -> HashMap<String, usize> {
let mut result: HashMap<String, usize> = HashMap::new();
for key in vec.iter() {
let val = result.entry(key.to_string()).or_insert(0);
*val += 1;
}
result
}
有人愿意分享更好的解决方案吗?非常感谢~
您可以做的一件事是避免创建新的 String
通过消耗(或移动)原始向量的值。像这样:
pub fn my_counter(vec: Vec<String>) -> HashMap<String, usize> {
let mut result: HashMap<String, usize> = HashMap::new();
for key in vec {
let val = result.entry(key).or_insert(0);
*val += 1;
}
result
}
注意更改后的函数签名:vec
现在是Vec<String>
, 不是 &Vec<String>
.如果出于某种原因,那是 Not Acceptable ,那么您真的无法避免创建新的 String
。 HashMap
的值的 key 。假设 N 是矢量项的数量,M 是唯一矢量项的数量。如果您知道您将在向量中有很多重复值(也就是说,M 远小于N),理论上您只创建 M 个新的 String
或许能够逃脱惩罚秒。但是,Rust 似乎没有提供稳定 方法来直接实现这一点。如果您可以使用 Nightly,可以尝试 raw_entry_mut()
.
另一种方法可能是先创建一个临时的 HashMap<&str, usize>
然后将其转换为所需的“完全拥有”HashMap<String, usize>
.然而,这很可能只会让事情变得更糟。这实际上取决于您拥有的 key 。使用短键和 M:N 的比率约为 0.5-1.0 是一回事,如果您使用长键且比率为 0.0001,则完全不同。
如果您对唯一键的数量有一个很好的想法,您肯定可以通过简单地创建 HashMap
来在一定程度上加快速度。与 HashMap::with_capacity(...);
.使用默认哈希器的替代方案在理论上也有帮助,尽管我只尝试过 FnvHashMap
甚至简称String
键我无法获得任何显着的加速。