Sorting scores to save it in file

Hello,

i need to store score when player dies and display hall of fame. But if two players have the same score, instead of sorting from pseudo alphabet order, i'd rather like to sort by growing timestamp. I want to show only top 5 players among vector of scores.
extern crate serde;

use serde::{Serialize, Deserialize};

#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Record {
    score_value: u32,
    player_name: String, //  does not implement `Copy`
    timestamp_fake: u32,
}

impl Record {
    pub fn new(score_value: u32, player_name: String, timestamp_fake: u32) -> Record {
        Record{
            score_value: score_value,
            player_name: player_name,
            timestamp_fake: timestamp_fake,
        }
    }
}

fn main() {
	let veryearlyscore = Record { score_value: 300, player_name: "veryearlyscore".to_string(), timestamp_fake: 5000 };
	let yesterdayscore = Record { score_value: 1500, player_name: "yesterdayscore".to_string(), timestamp_fake: 7000 };
	let myscore = Record { score_value: 800, player_name: "myscore".to_string(), timestamp_fake: 8000 };
	let friendscore = Record { score_value: 800, player_name: "friendscore".to_string(), timestamp_fake: 9000 };
  let forgottenscore = Record { score_value: 1000, player_name: "forgottenscore".to_string(), timestamp_fake: 4900 };
  let forgottenscore2 = Record { score_value: 1150, player_name: "forgottenscore2".to_string(), timestamp_fake: 4950 };
  let latescore = Record { score_value: 950, player_name: "latescore".to_string(), timestamp_fake: 9999 };


	let mut allscores :Vec<&Record> = Vec::new();
	allscores.push(&veryearlyscore);
	allscores.push(&yesterdayscore);
	allscores.push(&myscore);
	allscores.push(&friendscore);    

  println!("allscores  :  {:?}", allscores);
  println!("-------------------------------------------");
  allscores = allscores.sort_by_key(|h| (h.score_value, h.timestamp_fake));
  println!("allscores  :  {:?}", allscores);
  println!("-------------------------------------------");
  allscores = allscores.iter().rev().take(5);
  println!("-------------------------------------------");
  println!("{:?}", allscores);    
}

The sort_by_key method modifies the collection in place and does not return anything, so you just want

allscores.sort_by_key(|h| (h.score_value, h.timestamp_fake));

with no assignment. Additionally, you need to collect the iterator.

allscores = allscores.into_iter().rev().take(5).collect();

In this case I use into_iter as iter gives an iterator of references, and not just the integers. You can also do this to copy those references.

allscores = allscores.iter().copied().rev().take(5).collect();

The advantage of copied() is that into_iter destroys the vector it is called on, which copied() doesn't.

thank you alice for your helping answer, still remaining problem here:
for identical score, recents scores should appear after old ones.
the first player who hit 1000 points should appear on top of recent players with 1000 points.

You can reverse the ordering with Reverse.

use std::cmp::Reverse;

allscores.sort_by_key(|h| (h.score_value, Reverse(h.timestamp_fake)));

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.