我正在基于循环和模式匹配构建不同案例类对象的列表。 我想排除(跳过)遇到默认情况的项目(基本上是过滤列表,并在一个步骤中映射到类型)。
我可能对Scala太新了,看不到所有的可能性。我的尝试:
val events = for (ev <- data ) yield {
ev.sport match {
case "FOOTBALL" => new FootballEvent(ev)
case "SOCCER" => new SoccerEvent(ev)
case _ => None
}
}
之后我可以过滤列表,但我怀疑有一些花哨的Scala方式:)
如果您对如何做到最好,请告诉我们!
答案 0 :(得分:28)
不是它是yield语法,但你可以使用带模式匹配的collect:
val events = data.collect { ev => ev.sport match {
case "FOOTBALL" => new FootballEvent(ev)
case "SOCCER" => new SoccerEvent(ev)
}}
与众所周知的.map
和.foreach
不同,它不会在“其他”情况下失败,而只会丢弃不匹配的项目。
答案 1 :(得分:9)
for-yield
中的标准过滤器是使用x <- y if f(x,..)
获得的。以下是使用部分函数的示例。
val m: PartialFunction[Event, Event] = ev => ev.sport match {
case "FOOTBALL" => new FootballEvent(ev)
case "SOCCER" => new SoccerEvent(ev)
};
for { ev <- data if m.isDefindAt(ev)
val x = m(ev)
} yield x
// or, without the temporary binding:
for (ev <- data if m.isDefindAt(ev)) yield m(ev)
注意与另一个答案中提到的Traversable.collect
1 的相似性,该答案具有此签名def
collect[B](pf: PartialFunction[A, B]): CC[B]
并返回“将给定的部分函数pf应用到的新集合定义它的每个元素并收集结果“。
没有if
的替代方案是bwroga删除答案的变体:
for { ev <- data;
x <- ev.sport match {
case "FOOTBALL" => Some(new FootballEvent(ev))
case "SOCCER" => Some(new SoccerEvent(ev))
case _ => None
}
} yield x
通过随后在初始地图之后迭代无(即“0项”)或某些(即“1项”)进行过滤。
1 如果有人可以告诉我如何链接到“新”scaladoc中的个别方法,我将非常感激。