简体   繁体   中英

rust macro, how to control the different vec have the same length?

code first:

use std::collections::HashMap;
 macro_rules! arr{
    ([$($t:expr=>[$($c:expr),*]),*]) => {
       vec![
            $({
                let mut m = HashMap::new();
                m.insert($t, vec![$($c),*]);
                m
            }),*
       ]
    };
}

fn main() {
    let a = arr!([
        "A"=>[1,2,3],
        "B"=>[3,4]
    ]);
    println!("{:?}", a);
    //print:  [{"A": [1, 2, 3]}, {"B": [3, 4]}]
}

I have above macro to generate a vec, contains several HashMap, in which these HashMap value is a vec as well, {"A": [1, 2, 3]} => vec value length: 3, {"B": [3, 4]} => vec value length: 2, I wanna all the HashMap have the same length, how to write in the macro to control this?

You can change the macro so that it creates a block (second set of {} encapsulating the macro definition) that you can set helper variables in and do a second pass over your vector, resizing anything that is smaller than the largest array.

In this case I've resized the arrays with the default value of the type to keep it simple. You may wish to wrap the data in Some() .

This:

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

macro_rules! arr{
    ([$($t:expr=>[$($c:expr),*]),*]) => {{
       let mut max = 0;
       let mut result = vec![
            $({
                let mut m = HashMap::new();
                m.insert($t, vec![$($c),*]);
                // Simply unwrap here as we know we inserted at this key above
                max = cmp::max(max, m.get($t).unwrap().len());
                m
            }),*
       ];
       for m in result.iter_mut() {
           for v in m.values_mut() {
               if v.len() < max {
                   v.resize_with(max, Default::default);
               }
           }
       }
       result
    }};
}

fn main() {
    let a = arr!([
        "A"=>[1,2,3],
        "B"=>[3,4]
    ]);
    println!("{:?}", a);
    //print:  [{"A": [1, 2, 3]}, {"B": [3, 4]}]
}

Yields:

[{"A": [1, 2, 3]}, {"B": [3, 4, 0]}]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM