在这种情况下,我可以避免变异吗?

时间:2019-04-22 05:07:55

标签: scala

我正在尝试迭代一个列表,然后对每个项目进行范围检查并相应地累积分数。

挺直的。我觉得我正在以更传统的方式执行此操作,并创建了许多“ var”变量。

是否存在一种有效的功能/不变方式来实现此行为?

  var score_1 = 0
  var score_2 = 0
  var score_3 = 0
  var score_4 = 0
  var score_5 = 0

  val list = List(1,1,1,0.8,0.75,0.7,0.7,0.5,0.4,0.25,0.2,0.15,0.1)

  list.foreach( i => {
      i.toDouble match {
        case x if( x == 1.0 ) => score_1 += 1
        case x if( x >= 0.75 && x < 1 ) => score_2 += 1
        case x if( x >= 0.50 && x < 0.75) => score_3 += 1
        case x if( x >= 0.25 && x < 0.50) => score_4 += 1
        case x if( x >= 0 && x < 0.25 ) => score_5 += 1
        case _ => 
      }
    })

 println(score_1,score_2,score_3,score_4,score_5)

3 个答案:

答案 0 :(得分:2)

是的,您可以使用foldLeft来实现不变性,

case class Score(score1: Int,
                 score2: Int,
                 score3: Int,
                 score4: Int,
                 score5: Int,
                 score6: Int,
                 score7: Int,
                 score8: Int)

object Score {
  def empty = new Score(0, 0, 0, 0, 0, 0, 0, 0)
}

val myScore = list.foldLeft(Score.empty) {
  case (score, 1.0)                       => score.copy(score1 = score.score1 + 1)
  case (score, x) if x > 0.75 && x < 1    => score.copy(score2 = score.score2 + 1)
  case (score, 0.75)                      => score.copy(score3 = score.score3 + 1)
  case (score, x) if x > 0.50 && x < 0.75 => score.copy(score4 = score.score4 + 1)
  case (score, 0.50)                      => score.copy(score5 = score.score5 + 1)
  case (score, x) if x > 0.25 && x < 0.50 => score.copy(score6 = score.score6 + 1)
  case (score, 0.25)                      => score.copy(score7 = score.score7 + 1)
  case (score, x) if x >= 0 && x < 0.25   => score.copy(score8 = score.score8 + 1)
  case (score, _)                         => score
}

println(myScore) // Score(3,1,1,2,1,1,1,3)

答案 1 :(得分:1)

这是一种不同的方法,它利用分数断点平均分布这一事实:

val scores = Array.fill(5)(0)

list.foreach{ x =>
  val bucket = math.floor(x*4).toInt

  scores(bucket) += 1
}

这使用了可变的Array,但在这种情况下可能是最有效的解决方案。

答案 2 :(得分:-1)

感谢@Prayagupd ..好的答案。这很有帮助。同时,我正在尝试另一种实现此目标的方法。请随时让我知道您的想法。

val scoreMap = list.map( i => {
          i.toDouble match {
            case x if( x == 1.0 ) => (1,1)
            case x if( x >= 0.75 && x < 1 ) => (2,1)
            case x if( x >= 0.50 && x < 0.75) => (3,1)
            case x if( x >= 0.25 && x < 0.50) => (4,1)
            case x if( x >= 0 && x < 0.25 ) => (5,1)
            case _ => (0,0)
          }    
    }).groupBy(_._1).mapValues( _.map(_._2).sum ).toMap

   println(TreeMap(scoreMap.toSeq:_*)) //(1 -> 3, 2 -> 2, 3 -> 3, 4 -> 2, 5 -> 3)