2017-06-06 11 views
1

私のプログラムはスカラマップを受け取りますが、このマップを検証する必要があります(キーと値のペア)。例:キー値を検証し、値を許容可能な形式に変更します。まれに、マップを下位レイヤーに渡す前にキーを更新します。このマップを更新する必要はありませんが、サポートされていないキーや値があることが検出された場合に限ります。ただし、すべてのキーと値のペアをチェックする必要があります。このようスカラマップを検証するためのエレガントな方法

private def updateMap (parameters: Map[String, String]): Map[String, String] = { 

parameters.map{ 

    case(k,v) => k match { case "checkPool" => 


    (k, (if (k.contains("checkPool")) 
     v match { 
     case "1" => "true" 
     case _ => "false" 
     } 
    else v)) 

    case "Newheader" => (k.replace("Newheader","header"),v) 
    case _ =>(k,v) 
    } 


    case _ => ("","") 
} 

} 

検証を行うと、サポートするものにキー/値を変換するためのコードが上昇:私はこのようないくつかのことをやっています。 Scalaでこの検証を行うための、よりクリーンな方法がマップにありますか?

+0

キー値は "NewHeader"と "checkPool"に等しいか、より長い文字列の一部です(contains関数を使用します)?それらがキーストリングの一部である場合、Ramesh Maharjanのソローションは良好でなければ、よりクリーンな方法が存在します。 – Shaido

答えて

0

シンプルif else条件のマッチングが最良の選択であるように思わ

感謝。

def updateMap(parameters: Map[String, String]): Map[String, String] = { 
    parameters.map(kv => { 
    var key = kv._1 
    var value = kv._2 
    if(key.contains("checkPool")){ 
     value = if(value.equals("1")) "true" else "false" 
    } 
    else if(key.contains("Newheader")){ 
     key = key.replace("Newheader", "header") 
    } 
    (key, value) 
    }) 
} 

あなたはより多くのelseif条件

を追加することができます
3

あなたが互いの上にすべてのあなたのパターンを置く場合、それが明確になります。明確にするため

parameters.map{ 
    case ([email protected]"checkPool", "1") => k -> "true" 
    case ([email protected]"checkPool", _") => k -> "false" 
    case ("Newheader", v) => "header" -> v 
    // put here all your other cases 
    case (k, v) => k -> v //last possible case, if nothing other matches 
} 

、あなたはまた、部分的に異なるバリデータを置くことができます機能:

type Validator = PartialFunction[(String, String), (String, String) 
val checkPool: Validator = { 
    case ([email protected]"checkPool", "1") => k -> "true" 
    case ([email protected]"checkPool", _") => k -> "false" 
} 
val headers: Validator = { 
    case ("Newheader", v) => "header" -> v 
} 

あなたのmapにすべてのバリデータを1つずつ入れ:

parameters.map(
    checkPool orElse 
    headers orElse 
    ... orElse 
    PartialFunction(identity[(String, String)]) //this is the same as case (k, v) => k -> v 
) 
0

私はそれを正しく理解していれば、あなたの目的はマップにパッチを適用するために必要なコードの量を減らすことです。

もう1つの答えで提案されているように、アイデアは、更新ルールの定義と適用の間で分割されるため、ルールの適用方法を再定義することなく新しい更新が必要になるため、 。

ルールの定義は、キーから変換を定義する関数へのマップとしてモデル化できます。変換自体は、単純な関数の上にモデル化することができます。

ルールの適用は、これらの関数を適用し、それらを定義されたキーに適用することとして定義することができます。

sealed trait Patch extends (((String, String)) => (String, String)) 

final class PatchValue(update: String => String) extends Patch { 
    override def apply(pair: (String, String)): (String, String) = pair.copy(_2 = update(pair._2)) 
} 

final class PatchKey(update: String => String) extends Patch { 
    override def apply(pair: (String, String)): (String, String) = pair.copy(_1 = update(pair._1)) 
} 

final class MalleableMapPatching(rules: Map[String, Patch]) { 

    def updatePair(pair: (String, String)): (String, String) = { 
    rules.filterKeys(_ == pair._1).foldLeft(pair) { 
     case (pair, (_, patch)) => 
     patch(pair) 
    } 
    } 

    def update(parameters: Map[String, String]): Map[String, String] = 
    parameters.map(updatePair) 

} 

これでルール定義の部分が完成しました。これで、ルールのセットを適用できるようになりました。

val patchingRules = 
    Map(
    "checkPool" -> new PatchValue(value => if (value == "1") "true" else "false"), 
    "Newheader" -> new PatchKey(_ => "header") 
) 

val patcher = new MalleableMapPatching(patchingRules) 

私の解決策をもっとよく見たいと思ったら、here is the code on Github;あなたのコードのリファクタリングを検証する一連のテストを作成しました。

私はあなたの役に立つと思うかもしれません。

関連する問題