2017-10-20 12 views
1

私はScalaでSeq[String]を持っていて、もしに特定のStringが含まれていれば、別のリストに関連するメッセージを追加します。リストに追加される一連のif文の代わりのScala?

私は以下のようにリストに追加された一連のif文ではなく、これを行うためのよりスケーラブルな方法がありますか?あなたには、いくつかのScalaの反復可能オブジェクトの砂糖を使用したい場合は

val result = new ListBuffer[Err]() 

val malformedParamNames = // A Seq[String] 

if (malformedParamNames.contains("$top")) result += IntegerMustBePositive("$top") 
if (malformedParamNames.contains("$skip")) result += IntegerMustBePositive("$skip") 
if (malformedParamNames.contains("modifiedDate")) result += FormatInvalid("modifiedDate", "yyyy-MM-dd") 
... 

result.toList 

答えて

1

私はあなたが物事のスカラ風の道を求めるならば、多くの可能性がある警告すること

sealed trait Err 
case class IntegerMustBePositive(msg: String) extends Err 
case class FormatInvalid(msg: String, format: String) extends Err 

val malformedParamNames = Seq[String]("$top", "aa", "$skip", "ccc", "ddd", "modifiedDate") 

val result = malformedParamNames.map { v => 
    v match { 
    case "$top" => Some(IntegerMustBePositive("$top")) 
    case "$skip" => Some(IntegerMustBePositive("$skip")) 
    case "modifiedDate" => Some(FormatInvalid("modifiedDate", "yyyy-MM-dd")) 
    case _ => None 
    } 
}.flatten 


result.toList 

を使用します。

フラット化と組み合わせるマップ機能は

sealed trait Err 
case class IntegerMustBePositive(msg: String) extends Err 
case class FormatInvalid(msg: String, format: String) extends Err 

val malformedParamNames = Seq[String]("$top", "aa", "$skip", "ccc", "ddd", "modifiedDate") 

val result = malformedParamNames.flatMap { 
    case "$top" => Some(IntegerMustBePositive("$top")) 
    case "$skip" => Some(IntegerMustBePositive("$skip")) 
    case "modifiedDate" => Some(FormatInvalid("modifiedDate", "yyyy-MM-dd")) 
    case _ => None 
} 


result 
+0

おかげで、感じていますか? – Rory

+0

私はそれが理解しやすいと主張するだろうが、YMMV。 if文のアプローチでは、他のシーケンスの内容に基づいてシーケンスを構築していることを理解するためにそれぞれの作業を行う必要がありますが、map/flattenの存在によってその順序が明確になりますブノワ –

+1

例と対比して、これとのマイナーな意味上の違いがあります。この解決策では、質問のコードに繰り返しの要素はありません。これが重要な場合は、result.toSet.toListが重複除外されます。 –

0

ブノワのは、おそらくそれを行うのほとんどのScala風方法ですが、後からコードを読むことになるだろう誰に応じて、あなたがかもしれないがflatmap使用することによって単純化することができます別のアプローチが必要です。

// Some type definitions omitted 
val malformations = Seq[(String, Err)](
    ("$top", IntegerMustBePositive("$top")), 
    ("$skip", IntegerMustBePositive("$skip")), 
    ("modifiedDate", FormatInvalid("modifiedDate", "yyyy-MM-dd") 
) 

リストと順序が必要な場合siginificantです:

val result = (malformations.foldLeft(List.empty[Err]) { (acc, pair) => 
    if (malformedParamNames.contains(pair._1)) { 
    pair._2 ++: acc // prepend to list for faster performance 
    } else acc 
}).reverse // and reverse since we were prepending 

順序は重要ではない場合(順序は重要ではない場合、あなたの代わりにリストの設定を望む考えるかもしれませんが、 ):

val result = (malformations.foldLeft(Set.empty[Err]) { (acc, pair) => 
    if (malformedParamNames.contains(pair._1)) { 
    acC++ pair._2 
    } else acc 
}).toList // omit the .toList if you're OK with just a Set 

繰り返しIFSの述部は/不均一、より複雑であれば、彼らは応答が変更するかどうとして奇形の型は、変更する必要があるかもしれませんが、基本的なパターンをv柔軟なエリー。私は読み、それを維持しながら考えることができます

1

ほとんど「scalesque」バージョンは次のようになります。これはしかし、元のif文のアプローチということを読み、理解することが少し難しくなるよう

val map = scala.collection.immutable.ListMap(
    "$top" -> IntegerMustBePositive("$top"), 
    "$skip" -> IntegerMustBePositive("$skip"), 
    "modifiedDate" -> FormatInvalid("modifiedDate", "yyyy-MM-dd")) 

val result = for { 
    (k,v) <- map 
    if malformedParamNames contains k 
} yield v 

//or 

val result2 = map.filterKeys(malformedParamNames.contains).values.toList 
関連する問題