更简洁的HashMap初始化

and*_*man 26 hashmap rust

我用a HashMap来计算字符串中不同字符的出现次数:

let text = "GATTACA";
let mut counts: HashMap<char, i32> = HashMap::new();
counts.insert('A', 0);
counts.insert('C', 0);
counts.insert('G', 0);
counts.insert('T', 0);

for c in text.chars() {
    match counts.get_mut(&c) {
        Some(x) => *x += 1,
        None => (),
    }
}
Run Code Online (Sandbox Code Playgroud)

是否有更简洁或声明的方式来初始化HashMap?例如在Python中我会这样做:

counts = { 'A': 0, 'C': 0, 'G': 0, 'T': 0 }
Run Code Online (Sandbox Code Playgroud)

要么

counts = { key: 0 for key in 'ACGT' }
Run Code Online (Sandbox Code Playgroud)

fzy*_*cjy 49

我在官方文档中看到的另一种方式:

use std::collections::HashMap;

fn main() {
    let timber_resources: HashMap<&str, i32> =
    [("Norway", 100),
     ("Denmark", 50),
     ("Iceland", 10)]
     .iter().cloned().collect();
    // use the values stored in map
}
Run Code Online (Sandbox Code Playgroud)

  • @TommasoTheaCioni 好消息是,在 2021 版中,`into_iter()` 可在数组上工作[如预期](https://play.rust-lang.org/?version=nightly&amp;mode=debug&amp;edition=2021&amp;gist=86155b0b2fc7c09762e344b59e3a664b)! (4认同)

huo*_*uon 44

您可以使用迭代器来模拟字典理解,例如

let counts = "ACGT".chars().map(|c| (c, 0_i32)).collect::<HashMap<_, _>>();
Run Code Online (Sandbox Code Playgroud)

甚至 for c in "ACGT".chars() { counts.insert(c, 0) }.

此外,可以编写宏来允许任意值的简明初始化.

macro_rules! hashmap {
    ($( $key: expr => $val: expr ),*) => {{
         let mut map = ::std::collections::HashMap::new();
         $( map.insert($key, $val); )*
         map
    }}
}
Run Code Online (Sandbox Code Playgroud)

用过像let counts = hashmap!['A' => 0, 'C' => 0, 'G' => 0, 'T' => 0];.

  • 那绝对应该是std! (22认同)
  • 太棒了,给我(新手)一个宏的例子!谢谢! (2认同)
  • @PiotrZolnierek 这实际上是*标准*现在!(请参阅我的回答:)) (2认同)

Dan*_*ger 26

从 Rust 1.56 开始,您可以使用 键值对数组from()来构建 a 。Hashmap这使得可以简洁地初始化,而无需指定类型或编写宏。

use std::collections::HashMap;

fn main() {
    let m = HashMap::from([
        ('A', 0),
        ('C', 0),
        ('G', 0),
        ('T', 0)
    ]);
}
Run Code Online (Sandbox Code Playgroud)