如何计算scala中的学生成绩排名?

How to calculate student score rank in scala?

在我的问题中,每个学生都有一个 class,每个科目都有每个学生的分数。 现在我想获得所有学生在学校的排名,每个科目和总分的排名 class。 学生成绩数据是这样的:

userName class subject score
Mike     1     math    100
Jack     1     math    100
Jone     1     math    90
Helan    2     math    95
Mike     1     physics 100

预期结果是

userName  mathRank mathRank(class) physicsRank physicsRank(class) sumRank sumRank(class)
Mike      1        1               1           1                   1  1
Jack      1        1       
John      4        3       
Hellan    3        1       

我写了一些代码,下面是我的代码

  case class UserScore(userName:String,stuClass:Int,subject:String,score:Double)
  val userScores :Array[UserScore] = Array[UserScore](
  UserScore("Mike", 1, "math", 100D),
  UserScore("Jack", 1, "math", 100D),
  UserScore("Jone", 1, "math", 90D),
  UserScore("Helan", 2, "math", 95D),
  UserScore("Mike", 1, "physics", 95D))
//calculate school rank
  val subjectID2SchoolRanks = userScores.sortBy(_.score).reverse.groupBy(_.subject).map({
  case(subjectID, subjectUserScores)=>{
    var i:Int = 0
    subjectID->subjectUserScores.foldLeft(List[(UserScore,Int)]()){
      (userScoreRanks,userScore)=>{
         i= i+1
         if(userScoreRanks.nonEmpty&& userScoreRanks.last._1.score==userScore.score){
           userScoreRanks:+(userScore,userScoreRanks.last._2)
         }else {
           userScoreRanks:+(userScore,i)
         }
      }
    }
  }
})

但可能效率不高也不优雅,谁能给我一些建议,在此先感谢。

这段代码得到的结果与你的相同,但没有使用可变变量。

val subjectID2SchoolRanks = 
    userScores.groupBy(_.subject)
              .mapValues(_.sortWith(_.score >= _.score)
                          .zipWithIndex
                          .foldLeft((List[(UserScore,Int)](),-1.0,-1)){
                            case ((acc,pScore,pRank),(us,rank)) =>
                              if (pScore == us.score)
                                ((us,pRank)::acc, pScore, pRank)
                              else
                                ((us,rank+1)::acc, us.score, rank+1)
                          }._1.reverse)

我使用了很多相同的步骤,但顺序并不总是相同。 zipWithIndex 用于建立初始排名,然后 foldLeft 进行必要的调整。附加到 List 是一个相当低效的操作。通常最好通过 pre-pending 为它构建 List,然后在构建之后 reverse