多个选项Scala上模式匹配的有效方法

时间:2017-12-08 05:11:21

标签: scala

我有以下函数,它根据某些条件返回一个标志。

试着看看是否有更好的Scala方法来实现同样的目标?

基于人的状态,基本上有不同的规则可以在pass_ind标志上派生。

如果人员身份是学生或失业,则有一些收入规则,如果此人身份不在学生或失业状态,则有不同的规则适用于分数和&收入

def IncomeScreenStatus(status_cd: Option[String],
                                   score: Option[Int],
                                 income: Option[Double]) : String  = {

 var pass_ind : String = "F"

 if (score.isDefined && income.isDefined && status_cd.isDefined) {

        val score : Int = score.get
        val income : Double = income.get
        val status_cd : String = status_cd.get

        if (status_cd == "STUDENT" || status_cd == "UNEMPLOYMENT") {
          pass_ind = (status_cd, income) match {
            case ("UNEMPLOYMENT", income) if income <= 7000 => "P"
            case ("STUDENT", income) if income <= 18000 => "P"
            case _ => "F"
          }
        }
        else {
          pass_ind = (income, score) match {
            case (income, score) if (score < 100 || score > 150) && income <= 8500 => "P"
            case (income, score) if (score <= 167 && score >= 100) && income <= 10500 => "P"
            case _ => "F"
          }
        }

      }

    pass_ind


}

5 个答案:

答案 0 :(得分:1)

也许是这样的? (我没有尝试过,没有保证它是正确的。)

def IncomeScreenStatus( mb_status_cd : Option[String], mb_score : Option[Int], mb_income : Option[Double]) : String  = {

  def nsu( score : Int, income : Double ) = { // neither student nor unemployed
    if ( (score < 100 || score > 150) && income <= 8500 )         "P"
    else if ( (score <= 167 && score >= 100) && income <= 10500 ) "P"
    else                                                          "F"
  }

  ( mb_status_cd, mb_score, mb_income ) match {
    case ( Some( "STUDENT"                  ), Some( score ), Some( income ) ) if ( income <= 18000 ) => "P"
    case ( Some( "UNEMPLOYMENT"             ), Some( score ), Some( income ) ) if ( income <=  7000 ) => "P"
    case ( Some( "STUDENT" | "UNEMPLOYMENT" ), Some( _     ), Some( _      ) )                        => "F"
    case ( Some( _                          ), Some( score ), Some( income ) )                        => nsu( score, income )
    case _                                                                                            => "F"
  }
}

答案 1 :(得分:1)

这是第一次破解。

def IncomeScreenStatus(status_cd: Option[String]
                      ,score    : Option[Int]
                      ,income   : Option[Double]) : String  = {
  for {
    stat <- status_cd
    scr  <- score
    incm <- income
  } yield stat match {
    case "UNEMPLOYMENT" => if (incm <=  7000) "P" else "F"
    case "STUDENT"      => if (incm <= 18000) "P" else "F"
    case _ => if ((scr <  100 || scr >  150) && incm <=  8500 ||
                  (scr <= 167 && scr >= 100) && incm <= 10500) "P" else "F"
  }
}.getOrElse("F")

创建与传入参数同名的局部变量确实会使编译器感到困惑。

答案 2 :(得分:1)

首先,我对Scala采用的推荐代码风格的评论很少,

  • 变量/函数/ def名称应为camelCase
    • incomeScreenStatus代替IncomeScreenStatus
    • statusCd代替status_cd
    • passInd代替pass_ind

现在,

def incomeScreenStatus(statusCd: Option[String],
                       score: Option[Int],
                       income: Option[Double]) : String  = {
  (score, income, statusCd) match {
    case (Some(scoreV), Some(incomeV), Some(statusCdV)) => {
      (statusCdV, incomeV, scoreV) match {
        case ("UNEMPLOYMENT", _, _) if incomeV <= 7000 => "p"
        case ("STUDENT", _, _) if incomeV <= 18000 => "p"
        case _ if (scoreV < 100 || scoreV > 150) && incomeV <= 8500 => "P"
        case _ if (scoreV <= 167 && scoreV >= 100) && incomeV <= 10500 => "P"
        case _ => "F"
      }
    }
    case _ => "F"
  }

}

答案 3 :(得分:0)

在函数式编程中,最好使用小函数而不是大函数。我更喜欢做以下事情:

  def screenStudent(income:Double):String = {
    if (income <= 18000) "P" else "F"
  }
  def screenUnemployment(income:Double):String = {
    if (income <= 7000) "P" else "F"
  }
  def screenOthers(income:Double, score:Int):String = {
    (income, score) match {
      case (income, score) if (score < 100 || score > 150) && income <= 8500 => "P"
      case (income, score) if (score <= 167 && score >= 100) && income <= 10500 => "P"
      case _ => "F"
    }
  }
  def incomeScreenStatus(
    status_cd: Option[String],
    score: Option[Int],
    income: Option[Double]
  ) : String  =
  (status_cd , score, income) match {
    case (Some("STUDENT"), Some(_), Some(i)) => screenStudent(i)
    case (Some("UNEMPLOYMENT"), Some(_), Some(i)) => screenUnemployment(i)
    case (Some(_), Some(s), Some(i)) => screenOthers(i, s)
    case _ => "F"
  }

答案 4 :(得分:0)

由于您的示例需要定义每个字段,因此您可以将Task task; using(var something = GetSomething()){ task = something.TaskThatWillFailAndExplodeIfExecutedWhenSomethingIsDisplosed(); } task.Wait(); // BOOM 压缩在一起。我也想在我的案例陈述中使用提取器代替显式保护。

如果您的状态是有限集合,我还建议使用Option来表示它。

sealed trait
相关问题