How to find an element in vector of Option<String>

Viewed 1506

As a rust newbie I have a problem finding an element in a vector of Option using the "find" function:

#[derive(Debug)]
struct MyStruct {
    name: Option<String>,
    data: Option<String>
}

fn main() {
    let my_vec=vec![
        MyStruct{
            name:Some(String::from("name1")),
            data:Some(String::from("data1"))
        },
        MyStruct{
            name:Some(String::from("name2")),
            data:Some(String::from("data2"))
        }
    ];
    let search_string = String::from("name2");
    let found_record=my_vec.iter().find(|s| s.name == Some(search_string));
    println!("{:?}", found_record);
}

This code does not compile because of the comparison s.name == Some(search_string) because of a missing Copy trait. What would be the correct way for the "find" expression?

2 Answers

One option is to convert both your search_string and struct field to Option<&str> for comparison:

let found_record = my_vec.iter().find(
  |s| s.name.as_deref() == Some(search_string.as_ref()));

playground

The Error cause

Note that you are constructing an Option by using Some() inside the closure by moving the String.


Some solutions

  1. You can avoid that moving and make the closure capture by immutable reference by constructing the Option before it, as follows
let search_string = Some(String::from("name2"));
let found_record=my_vec.iter().find( |s| s.name == search_string);

  1. Or enter inside the Option, as follows
let search_string = String::from("name2");
let found_record=my_vec.iter().find( 
    |s| match &s.name{Some(name)=> name, _ => return false,} == &search_string
);


I don't prefer the approach

let found_record = my_vec.iter().find(
  |s| s.name.as_deref() == Some(search_string.as_ref()));

because it makes a new Some() every iteration unless if there is an optimization by the compiler.

Related