15

我正在基于循环和模式匹配构建不同案例类对象的列表。我想排除(跳过)符合默认情况的项目(本质上是过滤列表,并在一步中映射到类型)。

我可能对 Scala 太陌生,看不到所有的可能性。我的尝试:

    val events = for (ev <- data ) yield {

        ev.sport match {
            case "FOOTBALL" => new FootballEvent(ev)
            case "SOCCER" => new SoccerEvent(ev)
            case _ => None
        }

    }

之后我可以过滤列表,但我怀疑有一些花哨的 Scala 方法可以做到这一点:)

如果您对如何最好地完成此操作有任何想法,请告诉我!

4

2 回答 2

30

并不是说它是 yield 语法,而是您可以将 collect 与模式匹配一​​起使用:

val events = data.collect { ev => ev.sport match {
     case "FOOTBALL" => new FootballEvent(ev) 
     case "SOCCER"   => new SoccerEvent(ev)
}}

与众所周知的不同.map.foreach它不会在“其他”情况下失败,而只会丢弃不匹配的项目。

于 2013-02-27T21:07:57.360 回答
10

中的标准过滤器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)

请注意与另一个答案中提到的1的相似性,它具有此签名并返回“通过将给定的偏函数 pf 应用于定义它的每个元素并收集结果而产生的新集合”。Traversable.collectdef collect[B](pf: PartialFunction[A, B]): CC[B]

没有的替代方案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 中的各个方法,我将不胜感激。

于 2013-02-27T22:40:42.217 回答