2017-10-20 52 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