2017-10-20 51 views
1

我有一個Seq[String]在Scala中,如果Seq包含某些String S,我附上相關消息,另一份清單。斯卡拉替代系列如果添加到列表語句?

有沒有更「scalaesque」的方式做到這一點,而不是一系列if語句追加到列表像我有下面的?

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

如果你想使用一些斯卡拉iterables糖,我會用

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 

被警告如果你要求做的事情有很多可能性的階式的方式。

地圖功能與扁平化相結合,可通過使用flatmap

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

謝謝,感覺這是一個有點難以閱讀和理解,雖然,原來if語句的方法嗎? – Rory

+0

我認爲這很容易理解,但YMMV。在if語句的方法,你必須通過每個什麼,如果是做弄清楚你正在建立基於其他序列的內容序列,以自己的方式工作,而地圖的存在/扁平化使得該清楚Benoit的。 –

+1

有從這個對比的例子未成年人的語義差別:會有的問題的代碼沒有重複的元素,同時也可以在此解決方案。如果這是重要的,result.toSet.toList將重複數據刪除。 –

0

Benoit的可能是做的最階式的方式,但是這取決於誰去要閱讀後面的代碼進行簡化,你可能想要一個不同的方法。

// 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」版本我能想到的,同時保持它可讀將是:

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