Hoswoo
Hoswoo

Reputation: 63

How do you find an element in a Vector of tuples by comparing with a specific index in the tuple?

I have the following hash maps defined:

let mut adj_list: HashMap<String, Vec<String>>;
let mut adj_matrix: HashMap<String, Vec<(String, bool)>> = HashMap::new();

I also have the loop:

for (src, _neighbors) in self.adj_list.iter() {
    for (dest, _n) in self.adj_list.iter(){
        let d: &mut (String, bool) = adj_matrix.get_mut(src)
            .into_iter()
            .find(|&x| x == dest) // Error here
            .unwrap();
        // Do something with the tuple d
    }
}

The error I'm getting is:

adj_matrix.get_mut(src).into_iter().find(|&x| x == dest);
                                                ^^ no implementation for `Vec<(String, bool)> == String`

which makes sense to me, directly comparing a string to a tuple should make no sense. However I'm having trouble figuring out how to compare the dest string with the first element of the tuple.

I have tried:

adj_matrix.get_mut(src).into_iter().find(|&x| x.1 == dest);

but that gives me the error:

adj_matrix.get_mut(src).into_iter().find(|&x| x.1 == dest);
                                                ^ unknown field

What is the proper way to handle this?

Upvotes: 0

Views: 1154

Answers (1)

SirDarius
SirDarius

Reputation: 42969

Your adj_matrix variable is a HashMap of vectors.

The error you get gives you a hint:

^^ no implementation for Vec<(String, bool)> == String

You're not comparing a tuple to a string, you are comparing a Vec of tuples to a String, which does not make sense either.

Why do you have a Vec here while it looks like you should have a tuple?

Let's look at the types here:

let d: &mut (String, bool) = adj_matrix.get_mut(src) // --> Option<&mut Vec<(String, bool)>>
        .into_iter() // --> impl Iterator<Item = &mut Vec<(String, bool)>>
        .find(|&x| x == dest) // x -> Vec<(String, bool)>
        .unwrap();

This is caused by the fact that Option does implement IntoIter, and returns an iterator that returns 0 or 1 element, depending on whether it's a Some() or a None.

To fix your issue, you first need to make sure you actually have an entry for the src key.

It could look like something like this:

for (src, _neighbors) in self.adj_list.iter() {
    for (dest, _n) in self.adj_list.iter(){
        if let Some(v) = adj_matrix.get_mut(src) {
            let d: &mut (String, bool) = v
                .into_iter()
                .find(|&x| x == dest)
                .unwrap();
            // Do something with the tuple d
        } else {
            // src was not found
        }
    }
}

Upvotes: 1

Related Questions