How do I create a HashMap literal?

后端 未结 6 1511
再見小時候
再見小時候 2020-11-29 21:11

How I can create a HashMap literal in Rust? In Python I can do it so:

hashmap = {
   \'element0\': {
       \'name\': \'My New Element\',
       \'childs\':          


        
6条回答
  •  忘掉有多难
    2020-11-29 21:32

    There isn't a map literal syntax in Rust. I don't know the exact reason, but I expect that the fact that there are multiple data structures that act maplike (such as both BTreeMap and HashMap) would make it hard to pick one.

    However, you can create a macro to do the job for you, as demonstrated in Why does this rust HashMap macro no longer work?. Here is that macro simplified a bit and with enough structure to make it 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));
    }
    

    This has no additional allocation and is maximally efficient.


    In a nightly version of Rust, you can avoid both unneeded allocation and the need for a macro:

    #![feature(array_value_iter)]
    
    use std::array::IntoIter;
    use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
    use std::iter::FromIterator;
    
    fn main() {
        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);
    }
    

    This logic can then be wrapped back into a macro as well:

    #![feature(array_value_iter)]
    
    use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
    
    macro_rules! collection {
        // map-like
        ($($k:expr => $v:expr),* $(,)?) => {
            std::iter::Iterator::collect(std::array::IntoIter::new([$(($k, $v),)*]))
        };
        // set-like
        ($($v:expr),* $(,)?) => {
            std::iter::Iterator::collect(std::array::IntoIter::new([$($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);
    }
    

    See also:

    • Add hashmap, hashset, treemap, and treeset macros

提交回复
热议问题