Sorting complex vec structures


#1

Gentlefolk,

I have a complex vec structure with multi dimensional arrays as follows:

struct AthData {  
    reg : i32;
    rounds : [i32; 15],
    perfs : [[i32; 30]; 15],
}

impl AthData {
    fn new() -> AthData { AthData
        {
            reg : 0,
            rounds : [0; 15],
            perfs  : [[0; 30]; 15]
        }38
    fn sort(&self) -> i32
       { self. reg }3838

}

let mut ath_data = AthData::new();

I create the vec!

let mut ath_data_vec = vec!(AthData{reg : 0, rounds : [0; 15], perfs : [[0; 30]; 15]})

While processing the lines of the input file entries are pushed into the vec!

ath_data.reg = reg;
ath_data_vec.push(ath_data);

My problem is when trying to sort ath_data_vec using “sort_by_key” on the “reg” field.

I have two problems:
1/ All examples I have seen are for basic integer or strings.
I have finally got a clean compile with the following but does it sort? What about a reverse sort?

   (&mut *ath_data_vec).sort_by_key(|k| k.sort());

2/ Trying to access data extracted from the vec with a get. Example

      ath_get = ath_data_vec.get(1);

  Returns "ath_get_vec(1)"  as an "Option<&<unknown>> type. 

  Surely it should be AthData type???

Any help appreciated, Ian


#2

Your code with small improvements, few mistakes fixed and reformatted in a more idiomatic way, seems to work:

#[derive(Debug, Default)]
struct AthData {
    reg: i32,
    rounds: [i32; 15],
    perfs: [[i32; 30]; 15],
}

impl AthData {
    fn new() -> Self {
        Self {
            reg: 0,
            rounds: Default::default(),
            perfs: Default::default(),
        }
    }

    fn sort_field(&self) -> i32 {
        self.reg
    }
}

fn main() {
    let mut ath_data_vec = vec![AthData::default()];

    let mut ath_data = AthData::new();
    ath_data.reg = 10;
    ath_data_vec.push(ath_data);

    ath_data_vec.sort_by_key(|k| k.sort_field());
    let ath_get = ath_data_vec.get(1);
    println!("{:?}", ath_get);
}

See:
https://doc.rust-lang.org/nightly/std/cmp/struct.Reverse.html


#3

Leonardo,
Thank you for your response. It certainly tidied up many things and the sort worked!

However I have a problem accessing a field of ath_get.
I can access ath_data.reg with “ath_data.reg = 10”, but cannot access “ath_get.reg” after the ath_data_vec.get(1).

“ath_get” has a type "Option<&>, if I apply a type as follows:
“ath_get : AthData” (which I think is reasonable) the compiler complains with:

                               ath_data_vec.get(3);
|                              expected struct `AthData`, found enum `std::option::Option

Confused…
Any further help appreciated, Ian


#4

If you use get() you get an Option<&AthData>, that could be None if the index is past the vec bounds. The problems you note come from AthData not being Copy and Rust enforcing borrowing rules. This is one way to modify your field:

fn main() {
    let mut ath_data_vec = vec![AthData::default()];

    let mut ath_data = AthData::new();
    ath_data.reg = 10;
    ath_data_vec.push(ath_data);

    ath_data_vec.sort_by_key(|k| k.sort_field());

    if let Some(ath_get) = ath_data_vec.get_mut(1) {
        ath_get.reg = 11;
    }
    println!("{:?}", ath_data_vec);
}

#5

Leonardo,
Once again thank you, all fixed and working. Options & Results have given me a lot of problems.
I have always thought that C derived languages are left handed while a lot of my experience is from the right handed “Wirthian” world.

I battle on. Thanks, Ian.


#6

Rust is upper-kata[1] tentacled :slight_smile:

[1] https://en.wikipedia.org/wiki/Four-dimensional_space#Orthogonality_and_vocabulary


#7

… or perhaps pincered? :crab: