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);
}
```

alice
March 15, 2022, 4:48pm
#3
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
}
```

system
closed
June 13, 2022, 5:29pm
#5
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.