Removing object with highest attribute from Vec

Hi,
In my main I have a Vec called townList. I want to remove the town with the highest population and place that list in townList instead.
I currently have a Vec of Towns with multiple attributes like name and population.
How can I return the townList with the minus the town with the max population?

I currently get 'cannot borrow as mutable'. and annot borrow town_list as mutable, as it is not declared as mutable'
cannot borrow as mutable.
Evene though I set let mut town_list:Vec<Town> = Vec::new();
I assume that I'm not allowed to edit the list.

fn removeHighest( townList<Town>) -> Vec<Town> {
    let mut highest = townList.get(0);
    let mut index = 0;
    let mut lowest_index = 0;
    for town in townList.iter(){
        if town .population< highest.population {
            highest = town ;
            lowest_index = index;
        }
        index += 1;
    } 
    townList.remove(lowest_index);
    return townList;
}

You can add the mut keyword before the argument name to declare it as mutable:

fn removeHighest(mut townList: Vec<Town>) -> Vec<Town> {
1 Like

BTW, this can be shortened to:

let index = town_list.iter().enumerate()
    .max_by_key(|(_, t)| t.population)
    .map(|(i, _)| i).unwrap_or(0);
town_list.remove(index);
1 Like

Could this be expanded with another attribute as well? Using something like filter/ retain?
For example if my Town also has an enum called size which is Size::Small, Size::Medium, Size::Large. Could I remove a town that is the highest small town instead?

This is the closest I can think it could be

The error I get is missing lifetime specifier
What's going on?

fn get_highest_size_town(town_list:&mut Vec<Town>, sizeWanted: &Size)->&mut Town{
    let index = town_list.iter().enumerate()
    .retain(|t| t.size == sizeWanted)
    .min_by_key(|(_, s)| s.population)
    .map(|(i, _)| i).unwrap();
	
    return town_list.get_mut(index).unwrap();
}

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)
}
1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.