将序列中的某些项映射到None时的Typecheck

时间:2014-11-22 20:59:05

标签: scala sequences

以下代码遍历某些节点列表,并为某些节点创建ParagraphHeading个对象:

  abstract class Element    
  case class Paragraph(node: Node) extends Element
  case class Heading(mainNode: Node, textNode: Node) extends Element

  val elements =
      parent.child.map(n =>
        if (n.label == "p") Paragraph(n)
        else if (n.label.matches("h\d")) Heading(n, n.child.head)
        else None)

接下来,我想摆脱None元素并将elements传递给需要Seq[Element]的某个函数。但是,elements的类型为Seq[Product with Serializable]而不是Seq[Element]。为什么,以及如何使类型更强?

2 个答案:

答案 0 :(得分:4)

使用collect代替map仅保留您想要的元素:

val elements = parent.child.collect {
    case n if (n.label == "p") => Paragraph(n)
    case n if (n.label.matches("h\d")) => Heading(n, n.child.head))
}

在您传递给PartialFunction的{​​{1}}中未定义的任何内容都将被丢弃。

如果你打算丢弃这些元素,那么没有理由映射到collect。如果由于某种原因 想要保留None个实例,那么应将其他实例映射到None,以便您拥有Some[Element]

答案 1 :(得分:2)

我同意m-z collect在这里是一个很好的选择。您有时也可以选择使用flatMap,并为所需的值返回Some,为其他值返回None。由于Option被隐式转换为可迭代,flatMap会将列表展平为您想要的内容:

val elements = parent.child.flatMap(n =>
    if (n.label == "p") Some(Paragraph(n))
    else if (n.label.matches("h\d")) Some(Heading(n, n.child.head))
    else None)