【问题标题】:Is there any way to insert multiple entries into a HashMap at once in Rust?有没有办法在 Rust 中一次将多个条目插入 HashMap?
【发布时间】:2017-11-18 09:54:06
【问题描述】:

有没有办法在 Rust 中一次将多个条目插入到 HashMap 中?或者用多个条目初始化它?除了在您插入的每个元素上手动调用 insert 之外,还有什么其他方法吗?

编辑使用英文字母频率的示例:

我基本上想要:

let frequencies = { 
  'a': 0.08167, 
  'b': 0.01492, 
  ... 
  'z': 0.00074 
}

我知道我可以通过执行如下的 for 循环来实现相同的结果,但我想知道是否有一种方法可以做到这一点,而无需创建额外的数组然后循环它们,或更优雅的解决方案。

let mut frequencies = HashMap::new();
let letters = ['a','b','c', ...... 'z'];
let freqs = [0.08167, 0.01492, 0.02782, ......., 0.00074];
for i in 0..26 {
    frequencies.insert(letters[i], freqs[i]);
}

对于文字,我可以使用答案here,这可能适用于本示例,但我很好奇是否有办法做到这一点而不是文字,以防万一出现在未来。

【问题讨论】:

  • 你能解释一下你为什么想要这个吗?您是否试图避免多次输入“插入”? (如果是这样,则有一个 Hashmap 文字宏箱。)您是否试图避免调整 Hashmap 的大小? (如果是这样,那么您可以使用 'with_capacity' 对其进行初始化)您是否试图避免通过运行时来回往返? (如果是这样,我会告诉你不要担心,这并不像在 Python 或 JavaScript 中那样真正存在。)你是否试图缩短合并两个 Hashmap 所需的代码,因为你在很多地方都这样做?
  • 除了在每个元素上手动调用 insert — 是的,您可以使用循环,然后“手动”只调用一次 insert
  • 目的是用一些值来初始化HashMap。例如,英文字母频率。我基本上想要{'a':0.08167,'b':0.01492,...,'z':0.00074}。我想我可以创建一个键数组、一个值数组,然后遍历索引以插入像map.insert(letter[i], freq[i]) 这样的元素。我只是想知道是否有办法一次完成这一切。我将编辑我的问题以反映这一点。
  • 循环解决方案不好并没有真正的原因。我一直在以 Python 的方式考虑它,试图避免运行时问题,但这并不是什么大问题。我想它只是感觉不那么优雅。但是,唉。

标签: hashmap rust


【解决方案1】:

有没有办法在 Rust 中一次将多个条目插入到 HashMap 中?

是的,您可以使用来自Iterator 的值在extendHashMap 中使用,如下所示:

use std::collections::HashMap;

fn main() {
    let mut map = HashMap::new();
    map.extend((1..3).map(|n| (format!("{}*2=", n), n * 2)));
    map.extend((7..9).map(|n| (format!("{}*2=", n), n * 2)));
    println!("{:?}", map); // Prints {"1*2=": 2, "8*2=": 16, "7*2=": 14, "2*2=": 4}.
}

它甚至比手动调用insert 还要快一点,因为extend 使用Iterator 提供的大小提示来预先预留一些空间。

查看方法here, in map.rs的源代码。

或者用多个条目来初始化它?

这也是可能的,这要归功于 HashMap 实现了 FromIterator 特征。当集合实现FromIterator 时,您可以使用Iterator::collect 简写来构造它。考虑以下示例,它们都生成相同的地图:

use std::collections::HashMap;

fn main() {
    let mut map: HashMap<_, _> = (1..3).map(|n| (format!("{}*2=", n), n * 2)).collect();
    map.extend((7..9).map(|n| (format!("{}*2=", n), n * 2)));
    println!("{:?}", map); // Prints {"1*2=": 2, "8*2=": 16, "7*2=": 14, "2*2=": 4}.
}

use std::collections::HashMap;

fn main() {
    let map: HashMap<_, _> = (1..3)
        .chain(7..9)
        .map(|n| (format!("{}*2=", n), n * 2))
        .collect();
    println!("{:?}", map); // Prints {"1*2=": 2, "8*2=": 16, "7*2=": 14, "2*2=": 4}.
}

use std::collections::HashMap;
use std::iter::FromIterator;

fn main() {
    let iter = (1..3).chain(7..9).map(|n| (format!("{}*2=", n), n * 2));
    let map = HashMap::<String, u32>::from_iter(iter);
    println!("{:?}", map); // Prints {"1*2=": 2, "8*2=": 16, "7*2=": 14, "2*2=": 4}.
}

【讨论】:

  • 如果map的值类型是Vec,我想要extend方法扩展里面的Vec呢?我试过但发现 Vec 值被替换了,我的用例有什么解决方案吗?
猜你喜欢
  • 2016-07-28
  • 2019-06-11
  • 2021-03-23
  • 1970-01-01
  • 1970-01-01
  • 2020-05-04
  • 1970-01-01
  • 2021-10-08
  • 1970-01-01
相关资源
最近更新 更多