One to one

Macro


#![allow(unused_variables)]
fn main() {
macro_rules! stitch_one_to_one {
    ($left:expr, ($($left_key:tt),*), $right:expr, ($($right_key:tt),*)) => {{
        let mut right_by_key = HashMap::new();
        
        for item in $right {
            let right_key = ($( &item.$right_key ),*);
            right_by_key.entry(right_key).or_insert(item);
        }

        $left
            .iter()
            .filter_map(|item| {
                let left_key = ($( &item.$left_key ),*);
                match right_by_key.get(&left_key) {
                    Some(it) => Some((item, it.clone())),
                    None => {
                        eprintln!("Couldn't find items matching {:?} for {:?}.", left_key, item);
                        None
                    }
                }
            })
            .collect::<Vec<_>>()
    }};
}
}

Example usage


#![allow(unused_variables)]
fn main() {
fn show_one_to_one(
    user_emails: &[UserEmail],
    email_colors: &[EmailColor],
) {
    let items = stitch_one_to_one!(
        user_emails,
        (email),
        email_colors,
        (email)
    );

    let lookup: HashMap<Username, Color> = items
        .iter()
        .map(|(left, right)| {
            (
                left.username.to_string(),
                right.color.to_string(),
            )
        })
        .collect();

    println!("lookup = {:#?}", lookup);
}
}