仅在模式匹配时才产生

时间:2013-02-27 21:00:51

标签: scala for-loop pattern-matching yield

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

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

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

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

    }

之后我可以过滤列表,但我怀疑有一些花哨的Scala方式:)

如果您对如何做到最好,请告诉我们!

2 个答案:

答案 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中的个别方法,我将非常感激。