如何在Rust中创建HashMap文本?在Python中,我可以这样做:

hashmap = {
   'element0': {
       'name': 'My New Element',
       'childs': {
           'child0': {
               'name': 'Child For Element 0',
               'childs': {
                   ...
               }
           }
       }
   },
   ...
}

然后像这样走:

type Node struct {
    name string
    childs map[string]Node
}

hashmap := map[string]Node {
    "element0": Node{
        "My New Element",
        map[string]Node {
            'child0': Node{
                "Child For Element 0",
                map[string]Node {}
            }
        }
    }
}

推荐答案

Rust中没有映射文字语法.我不知道原因是什么,但我预计,有多个数据 struct 的行为类似于 map (例如BTreeMapHashMap),因此很难 Select 一个.

Rust 1.56

许多集合现在使用FromInto从数组参数提供转换:

use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};

fn main() {
    let s = Vec::from([1, 2, 3]);
    println!("{:?}", s);

    let s = BTreeSet::from([1, 2, 3]);
    println!("{:?}", s);

    let s = HashSet::from([1, 2, 3]);
    println!("{:?}", s);

    let s = BTreeMap::from([(1, 2), (3, 4)]);
    println!("{:?}", s);

    let s = HashMap::from([(1, 2), (3, 4)]);
    println!("{:?}", s);
}

对于某些语法,可以将此逻辑包装回宏:

use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};

macro_rules! collection {
    // map-like
    ($($k:expr => $v:expr),* $(,)?) => {{
        core::convert::From::from([$(($k, $v),)*])
    }};
    // set-like
    ($($v:expr),* $(,)?) => {{
        core::convert::From::from([$($v,)*])
    }};
}

fn main() {
    let s: Vec<_> = collection![1, 2, 3];
    println!("{:?}", s);

    let s: BTreeSet<_> = collection! { 1, 2, 3 };
    println!("{:?}", s);

    let s: HashSet<_> = collection! { 1, 2, 3 };
    println!("{:?}", s);

    let s: BTreeMap<_, _> = collection! { 1 => 2, 3 => 4 };
    println!("{:?}", s);

    let s: HashMap<_, _> = collection! { 1 => 2, 3 => 4 };
    println!("{:?}", s);
}

Rust 1.51

从Rust 1.51开始,您可以使用按值数组迭代器和FromIterator来收集到多种集合中:

use std::array::IntoIter;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::iter::FromIterator;

fn main() {
    // Rust 1.53
    let s = Vec::from_iter([1, 2, 3]);
    println!("{:?}", s);

    // Rust 1.51
    let s = Vec::from_iter(IntoIter::new([1, 2, 3]));
    println!("{:?}", s);

    let s = BTreeSet::from_iter(IntoIter::new([1, 2, 3]));
    println!("{:?}", s);

    let s = HashSet::<_>::from_iter(IntoIter::new([1, 2, 3]));
    println!("{:?}", s);

    let s = BTreeMap::from_iter(IntoIter::new([(1, 2), (3, 4)]));
    println!("{:?}", s);

    let s = HashMap::<_, _>::from_iter(IntoIter::new([(1, 2), (3, 4)]));
    println!("{:?}", s);
}

请注意,在Rust 1.53中,并不总是需要std::array::IntoIter.

对于某些语法,可以将此逻辑包装回宏:

use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};

macro_rules! collection {
    // map-like
    ($($k:expr => $v:expr),* $(,)?) => {{
        use std::iter::{Iterator, IntoIterator};
        Iterator::collect(IntoIterator::into_iter([$(($k, $v),)*]))
    }};
    // set-like
    ($($v:expr),* $(,)?) => {{
        use std::iter::{Iterator, IntoIterator};
        Iterator::collect(IntoIterator::into_iter([$($v,)*]))
    }};
}

fn main() {
    let s: Vec<_> = collection![1, 2, 3];
    println!("{:?}", s);

    let s: BTreeSet<_> = collection! { 1, 2, 3 };
    println!("{:?}", s);

    let s: HashSet<_> = collection! { 1, 2, 3 };
    println!("{:?}", s);

    let s: BTreeMap<_, _> = collection! { 1 => 2, 3 => 4 };
    println!("{:?}", s);

    let s: HashMap<_, _> = collection! { 1 => 2, 3 => 4 };
    println!("{:?}", s);
}

这些解决方案避免了不必要的分配和重新分配.

另见:

Previous versions

您可以创建一个宏来完成这项工作,如Why does this rust HashMap macro no longer work?所示.这是一个稍微简化了一点的宏,它有足够的 struct 使其成为runnable in the playground:

macro_rules! map(
    { $($key:expr => $value:expr),+ } => {
        {
            let mut m = ::std::collections::HashMap::new();
            $(
                m.insert($key, $value);
            )+
            m
        }
     };
);

fn main() {
    let names = map!{ 1 => "one", 2 => "two" };
    println!("{} -> {:?}", 1, names.get(&1));
    println!("{} -> {:?}", 10, names.get(&10));
}

该宏避免分配不需要的中间值Vec,但它不使用HashMap::with_capacity,所以在添加值时可能会对HashMap进行一些无用的重新分配.可以使用更复杂的宏来计算值,但性能方面的好处可能不是大多数使用宏的人都会受益的.

Rust相关问答推荐

如何在tauri—leptos应用程序中监听后端值的变化?""

如何处理动态 struct 实例化?

如果A == B,则将Rc A下推到Rc B

这种获取-释放关系是如何运作的?

为什么这个变量不需要是可变的?

允许 rust 迹 struct 条目具有多种类型

如何将实现多个特征的 struct 传递给接受这些特征为&;mut?

用于实现获取 struct 体 id 的特征规范

如何获取光标下的像素 colored颜色 ?

借来的价值生命周期 不够长,不确定为什么它仍然是借来的

Rust编译器通过哪些规则来确保锁被释放?

当在lambda中通过引用传递时,为什么会出现终身/类型不匹配错误?

有没有办法通过命令获取 Rust crate 的可安装版本列表?

使用 `clap` 在 Rust CLI 工具中设置布尔标志

RAII 模式的 Rust 解决方案,用于在 new() 和 drop() 上修改另一个对象

隐式类型闭包的错误生命周期推断

为什么这个闭包没有比 var 长寿?

类型组的通用枚举

如何将 while 循环内的用户输入添加到 Rust 中的向量?

为什么当borrow 变量发生变化时,borrow 变量不会改变?