2017-12-08 8 views
0

いくつかの条件に基づいてフラグを返す以下の関数があります。複数のオプションでのパターンマッチングの有効な方法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 


} 
+0

if(score.isDefined && income.isDefined && status_cd.isDefined)の 'else'はどうですか? –

+0

これ以外の場合、pass_indは "F" – shiv455

答えて

1

まず第一に、私はスカラ座で採択された推奨コード・スタイルに関するいくつかのコメントがあり、

  • 変数/関数/ DEF名がcamelCase
    • incomeScreenStatusの代わりIncomeScreenStatusことになっています。
    • statusCd代わりの代わりに、関数型プログラミングにおいて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" 
    } 

} 
+0

このコードは、IncomeScreenStatus(Some( "STUDENT")、None、Some(4000))として呼び出されたとき "F"を返しますが、期待される出力は "P" – shiv455

+0

あなたのコード - 'if(score.isDefined && income.isDefined && status_cd.isDefined){'? 'None'にこれらの3つのオプションがある場合、コードは' 'F ''を返します。それでは、期待される出力はどのように '' P ''ですか?あなたは答えのどこにでも指定しなかった。 –

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

ここでは最初の亀裂です。

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") 

渡されたパラメータと同じ名前のローカル変数を作成すると、実際にコンパイラが混乱します。

+0

Noneはここでも処理されますか? – shiv455

+0

このコードは、IncomeScreenStatus(Some( "UNEMPLOYMENT")、None、Some(4000))として呼び出されたときに "F"を返しますが、期待される出力は "P"です – shiv455

+0

@ shiv455;はい「なし」がここで処理されます。それはあなたの質問に投稿したコードと同じエフェクト(よりきれいで簡潔に)(すべての構文エラーが修正された後)に処理されます。この例の入力では期待される出力が '' P ''ですが、それはあなたのコードが生成する結果ではありません。いずれかの入力が 'None'の場合、' 'F" 'ならば出力されます。それが正しい結果でない場合は、あなたの質問にコードを修正する必要があります。 – jwvh

0

status_cd

  • passInd、小さな機能の代わりに大きなものを持っている方がよいです。

    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" 
        } 
    
  • +0

    入力 '(Some(" STUDENT ")、None、Some(1800))'はOPのコードと異なる結果を返します。 – jwvh

    +0

    ええ、ありがとう、それを修正した –

    0

    をあなたの例を定義する各フィールドを必要とするので、あなたが一緒にOption Sを圧縮することができます:私は以下のように何かをすることを好むだろう。私はまた、私のケースステートメントの明示的なガードの代わりにエクストラクタを使用するのが好きです。

    ステータスが有限集合の場合は、sealed traitを使用することをおすすめします。

    object Example { 
    
        sealed trait Status 
        case object Student extends Status 
        case object Unemployed extends Status 
        case object Other extends Status 
    
        object PoorStudent { 
        def unapply(income: Int) = if (income <= 18000) Some(income) else None 
        } 
    
        object PoorUnemployed { 
        def unapply(income: Int) = if (income <= 7000) Some(income) else None 
        } 
    
        object IncomeScoreRange { 
        def unapply(score: Int, income: Double) = 
         if (((score < 100 || score > 150) && income <= 8500) || (income <= 10500 && (100 to 167 contains score))) 
         Some((score, income)) 
         else 
         None 
        } 
    
        def compute(status: Option[Status], score: Option[Int], income: Option[Double]): String = { 
    
        (status, score, income).zipped 
         .collect { 
         case (Student, _, PoorStudent(_))     => "P" 
         case (Unemployed, _, PoorUnemployed(_))    => "P" 
         case (Other, IncomeScoreRange(_, _))     => "P" 
         } 
         .headOption 
         .getOrElse("F") 
        } 
    } 
    
    関連する問題