collections - 构建字符计数 HashMap 的惯用 Rust 方法是什么?
问题描述
我想计算字符串中每个字母的出现次数。目标是建立一个HashMap<char,i32>
键是字符串中的所有字符,值是出现次数。
假设我正在遍历char
字符串或输入文件中的值。对于 each char
,如果还没有遇到,我需要将它HashMap
作为新的键添加到 1 中,但如果之前已经见过,我需要增加值。
这是有效的代码。请耐心等待,我对 Rust 很陌生:
use std::collections::HashMap;
fn main() {
let mut letter_counts: HashMap<char,i32> = HashMap::new();
let input_string = "Hello, world!";
let char_vec: Vec<char> = input_string.to_lowercase().chars().collect();
for c in char_vec {
if let Some(x) = letter_counts.get_mut(&c) {
*x = *x + 1;
} else {
letter_counts.insert(c,1);
}
}
println!("{:?}",letter_counts);
}
我想知道的是,在 Rust 中是否有一种惯用的方法来做到这一点?通过惯用语,我的意思是有一个标准库类型(如 Python's defaultdict
)或 HashMap 上的一个方法(如 Java's HashMap.computeIfAbsent
),与我所做的手动编码算法相比,它会使这个更简单、更清晰和/或更不容易出错?
解决方案
Entry
如果您使用界面,这对于您想要做的事情可能会更容易一些,并且可能更惯用:
use std::collections::HashMap;
fn main() {
let mut letter_counts: HashMap<char,i32> = HashMap::new();
let input_string = "Hello, world!";
let char_vec: Vec<char> = input_string.to_lowercase().chars().collect();
for c in char_vec {
*letter_counts.entry(c).or_insert(0) += 1;
}
println!("{:?}",letter_counts);
}
如果条目不存在,您可以创建该条目并同时对其进行修改。
如果你想要一些更实用的东西,你可以这样做:
use std::collections::HashMap;
fn main() {
let input_string = "Hello, world!";
let letter_counts: HashMap<char, i32> =
input_string
.to_lowercase()
.chars()
.fold(HashMap::new(), |mut map, c| {
*map.entry(c).or_insert(0) += 1;
map
});
println!("{:?}", letter_counts);
}
这使用折叠来累积项目。
如果您正在寻找一个计算项目频率的标准库函数,那么没有。函数式方法足够优雅,我个人并不认为这是一个错误,而且在这种情况下,我通常会使用这种方法来处理大多数正常、惯用的 Rust 代码。使用迭代器在 Rust 中很常见。
正如其他人所提到的,对于某些情况,肯定有更专业的替代方法。
推荐阅读
- javascript - 如何让我的网页显示来自 JavaScript 函数的图像?
- g1ant - 为什么具有隐藏值的 setattribute 不隐藏徽标?
- ios - Cordova IOS 不会构建
- php - 如何使用foreach循环从数据库中获取数据?
- php - 在 ubuntu 18.04 中卸载 php 7
- unity3d - 如何检查该对象没有被另一个对象隐藏?
- arduino - 如何使用 Adafruit_Fingerprint.h 验证指纹是否存在并注册?
- python - 有没有办法告诉 pylint 不要对函数的 redefined-outer-name 发出警告?
- alert - 测试规则 AlertManager 失败:yaml:解组错误:第 1 行:在 main.unitTestFile 类型中找不到字段组
- r - 从核密度计算质心