This is a bit more complicated because your function takes two different borrowed references as input, and returns one as output. The compiler can't tell which of these three references are related. You must explicitly tell it that the &Vec<Town>
and &Town
have the same lifetime:
fn get_highest_size_town<'t>( // Create a lifetime parameter 't.
town_list: &'t mut Vec<Town>, // `town_list` has lifetime 't.
sizeWanted: &Size)
-> &'t mut Town { // So does the return type.
This tells the compiler that the Vec<Town>
must remain borrowed as long as returned &mut Town
reference is in use.
You can probably simplify this function by making it take Size
by value instead of by reference. Now there is just one input reference and one output reference, so the compiler will automatically give them the same lifetime without being told:
fn get_highest_size_town(
town_list: &mut Vec<Town>,
sizeWanted: Size)
-> &mut Town {
Passing around Size
by value will be simpler it implements the Copy
trait, so you don't need to explicitly clone or move it. It also needs to implement PartialEq
so you can compare it with the ==
operator:
#[derive(PartialEq, Copy, Clone)]
enum Size { Small, Medium, Large }
In the body of your function, the method you want is Iterator::filter
, which you can use like this. Note that I removed enumerate()
since we only need the item itself, not its index, and used iter_mut()
because we need a mutable reference:
fn get_highest_size_town(
town_list: &mut Vec<Town>,
sizeWanted: Size)
-> &mut Town {
town_list
.iter_mut()
.filter(|t| t.size == sizeWanted)
.max_by_key(|t| t.population)
.unwrap()
}
Note that unwrap()
will panic if there are no matching towns. You might want to return an Option instead, if you don't want your program to abort when this happens:
/// Returns `Some(town)` or `None` (if there are no towns of size `sizeWanted`)
fn get_highest_size_town(
town_list: &mut Vec<Town>,
sizeWanted: Size)
-> Option<&mut Town> {
town_list
.iter_mut()
.filter(|t| t.size == sizeWanted)
.max_by_key(|t| t.population)
}