'Why am I getting double reference to type when iterating over vector of references? [duplicate]

Consider following minimum reproducible. I have a vector of objects and I have a hashmap where each value is a vector of references to objects from the objects vector.

I then get a value from HashMap (which is a reference to vector of references) and I want to filter it so I get vector of references to objects. However, when I do iter-filter-collect, compiler claims that I am iterating over &&O (instead of &O I expect) and errors out.

I can "fix" that error by uncommenting the map function which dereferences iterated objects, however I don't think that is the correct thing to do here.

use std::collections::HashMap;

struct O {
    a: i32,
    b: i32,
}

fn main() {
    let mut objects = vec![
        O { a: 1, b: 0 },
        O { a: 2, b: 0 },
        O { a: 3, b: 0 },
        O { a: 4, b: 1 },
    ];

    let mut b_to_o: HashMap<i32, Vec<&O>> = HashMap::new();
    for o in &objects {
        b_to_o.entry(o.b).or_insert(Vec::new()).push(&o);
    }

    let b_zero: &Vec<&O> = b_to_o.get(&0).unwrap();
    let b_zero_a_odd: Vec<&O> = b_zero
        .iter()
        .filter(|o| o.a % 2 == 0)
        //.map(|o| *o)
        .collect::<Vec<&O>>();
}

NOTE: Vector of objects doesn't have to be mut in this example, but it has to be in the code I am reproducing.



Solution 1:[1]

You have a Vec<&T> and iter yields &Output, where Output is the inner type of the Vec, in this case &T, you you get: &Output => &&T.

There is nothing wrong on dereferencing the double reference, you can use map, or you can use filter_map as a single step (notice the pattern mathing in the closure parameter to dereference directly |&o|):

let b_zero_a_odd: Vec<&O> = b_zero
    .iter()
    .filter_map(|&o| if o.a % 2 == 0 { Some(o) } else { None })
    .collect::<Vec<&O>>();

Playground

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Netwave