# Get Indices of Sorted Vec of Structs with Float Fields

Hi,

I am trying to get the indices of a sorted vec of structs which contains float fields. On Stack Overflow, I found a similar question: sorting - How to get the indices that would sort a vector in Rust? - Stack Overflow. However, in my case the struct contains float fields. Here is a sample code of the problem:

``````struct Player {
power: f64,
weight: f64
}

/* From https://stackoverflow.com/a/69764256 */
fn argsort<T: Ord>(data: &[T]) -> Vec<usize> {
let mut indices = (0..data.len()).collect::<Vec<_>>();
indices.sort_by_key(|&i| &data[i]);
indices
}

fn main() {
let n_players: usize = 2;
let mut players: Vec<Player> = Vec::with_capacity(n_players);
players.push(Player {
power: 10.0,
weight: 50.0
});
players.push(Player {
power: 15.0,
weight: 70.0
});

/* Error */
let indices: Vec<usize> = argsort(&players);
}

``````

I can sort the vector itself using the method mentioned in Sort a Vector - Rust Cookbook.

``````players.sort_by(|a, b| a.power.partial_cmp(&b.power).unwrap());
``````

But I don't know how I can use the `sort_by` function to compare floats in my case. Could someone guide me, on the proper way to integrate the float comparision in the `argsort` function above?

Thank you.

You could add an extra argument to compare by. Similar to `sort` vs `sort_by` – the latter has an additional `FnMut(&T, &T) -> Ordering` argument – you can create

``````fn argsort_by<T, F>(data: &[T], mut compare: F) -> Vec<usize>
where
F: FnMut(&T, &T) -> Ordering,
{
// TODO
}
``````

and then call this as

``````argsort_by(&players, |a, b| a.power.partial_cmp(&b.power).unwrap())
``````

If you want to come up with the implementation of `argsort_by` yourself, give it a go. Otherwise here’s a solution:

Click to expand.
``````struct Player {
power: f64,
weight: f64,
}

fn argsort_by<T, F>(data: &[T], mut compare: F) -> Vec<usize>
where
F: FnMut(&T, &T) -> std::cmp::Ordering,
{
let mut indices = (0..data.len()).collect::<Vec<_>>();
indices.sort_by(|&i, &j| compare(&data[i], &data[j]));
indices
}

fn main() {
let n_players: usize = 2;
let mut players: Vec<Player> = Vec::with_capacity(n_players);
players.push(Player {
power: 10.0,
weight: 50.0,
});
players.push(Player {
power: 15.0,
weight: 70.0,
});

let indices: Vec<usize> = argsort_by(&players, |a, b| a.power.partial_cmp(&b.power).unwrap());

dbg!(&indices);
}
``````

Assuming that `data` is an array of floats:

``````indices.sort_by(|&i1, &i2| data[i1].partial_cmp(&data[i2]).unwrap())
``````
1 Like

Thank you all for the help! I ended up modifying the function as follows:

``````fn get_sorted_indices(players: &[Player]) -> Vec<usize> {
let mut indices = (0..players.len()).collect::<Vec<_>>();
indices.sort_by(|&a, &b| players[a].power.partial_cmp(&players[b].power).unwrap());
indices
}
``````

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.