如何初始化一片 HashMap?

How do I initialize a slice of HashMaps?

我有一种情况需要 HashMap 的切片,切片的长度由一个常量指定。怎么初始化这样的野兽?

use std::collections::HashMap;
use std::default::Default;

const LENGTH: usize = 10;

fn main() {
    let f: [HashMap<String, u32>; LENGTH] = ???;
}

我已经尝试了 ???现货:

Default::default()
[HashMap::new(); LENGTH]
[Default::default(); LENGTH]
iter::repeat(HashMap::new()).take(LENGTH).collect().as_slice()

每一个都给我不同的错误:

test.rs:7:45: 7:61 error: the trait `core::default::Default` is not implemented for the type `[std::collections::hash::map::HashMap<collections::string::String, u32>; 10]` [E0277]
test.rs:7     let f: [HashMap<String, u32>; LENGTH] = Default::default();
                                                      ^~~~~~~~~~~~~~~~

test.rs:7:45: 7:69 error: the trait `core::marker::Copy` is not implemented for the type `std::collections::hash::map::HashMap<collections::string::String, u32>` [E0277]
test.rs:7     let f: [HashMap<String, u32>; LENGTH] = [HashMap::new(); LENGTH];
                                                      ^~~~~~~~~~~~~~~~~~~~~~~~

test.rs:7:45: 7:73 error: the trait `core::marker::Copy` is not implemented for the type `std::collections::hash::map::HashMap<collections::string::String, u32>` [E0277]
test.rs:7     let f: [HashMap<String, u32>; LENGTH] = [Default::default(); LENGTH];
                                                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~

test.rs:8:45: 8:107 error: the type of this value must be known in this context
test.rs:8     let f: [HashMap<String, u32>; LENGTH] = iter::repeat(HashMap::new()).take(LENGTH).collect().as_slice();
                                                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

这里有什么我遗漏的特殊魔法吗?还是我遇到了错误?

它不是切片,而是固定大小的数组。

您不能创建包含某些内容的切片,因为切片只是对属于其他内容(如数组或向量)的内存的“视图”。

Rust < 1.52 中的固定大小数组通常没有用。那是因为 Rust 还不支持带有整数参数的泛型类型,但是 Rust 中几乎所有的东西都是作为特征(泛型)实现的,所以它们不适用于数组。

您需要使用 Vec

使用MaybeUninit是我能想到的最好的方法。它的文档中有完全相同的内容:initializing-an-array-element-by-element.

playground

use std::collections::HashMap;
use std::mem::{MaybeUninit, transmute};

const LENGTH: usize = 10;

fn main() {
    let _data: [HashMap<String, u32>; LENGTH] = {
        let mut data: [MaybeUninit<HashMap<String, u32>>; LENGTH] = unsafe {
            MaybeUninit::uninit().assume_init()
        };

        for elem in &mut data[..] {
            *elem = MaybeUninit::new(HashMap::new());
        }

        unsafe { transmute::<_, [HashMap<String, u32>; LENGTH]>(data) }
    };
}