【问题标题】:What is the idiomatic Rust way to build a HashMap of character counts? [duplicate]构建字符计数 HashMap 的惯用 Rust 方法是什么? [复制]
【发布时间】:2021-01-18 12:39:55
【问题描述】:

我想计算字符串中每个字母的出现次数。目标是建立一个HashMap<char,i32>,其中键是字符串中的所有字符,值是出现次数。

假设我从字符串或输入文件中循环遍历char 值。对于每个char,如果还没有遇到过,我需要把它添加到HashMap作为新的key,值为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 的 defaultdict),或 HashMap 上的一个方法(如 Java 的 HashMap.computeIfAbsent),这将使这比手动编码更简单、更清晰和/或更不容易出错算法和我一样吗?

【问题讨论】:

  • 有一个frequency_hashmap crate(我没用过)。
  • @JohnKugelman 类似的问题,但提问者接受了一个使代码“更短”而不是惯用的答案。有点像“代码高尔夫”的答案。

标签: collections rust hashmap


【解决方案1】:

如果您使用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 中使用迭代器很常见。

正如其他人所提到的,对于某些情况,当然有更专业的替代方法。

【讨论】:

  • Entry 对我来说是新的。我认为.entry(c).or_insert(0)这行短语是我丢失的关键!
猜你喜欢
  • 2014-02-17
  • 2022-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-23
相关资源
最近更新 更多