如何处理scala for yield循环中不存在的值?



我正在拉解析一个xml文件,该文件可能有也可能没有一个名为<Popular>的元素元素<EName>

的例子:

<Info>
<Enterprise>
<EName>
<Legal>Cool company</Legal>
</EName>
</Enterprise>
<Enterprise>
<EName>
<Legal>Cool company2</Legal>
<Popular>The company 2</Popular>
</EName>
</Enterprise>
</Info>

我使用scala缩放xml,像这样:

val Info = NoNamespaceQName("Info")
val Enterprise = NoNamespaceQName("Enterprise")
val EName = NoNamespaceQName("EName")
val Legal = NoNamespaceQName("Legal")
val Popular = NoNamespaceQName("Popular")
val EnterprisePath = List(Info, Enterprise)
    val itr =  iterate(EnterprisePath, xml)
    for {
      enterprise <- itr
      enterpriseName <- enterprise * EName * Legal
      enterprisePopularName <- enterprise * EName * Popular 
    } {
      // Do fun stuff
      Logger.info("enterprise: "+enterpriseName + " "+enterprisePopularName)
}

当Popular元素不存在时,不会执行for语句,也不会执行yield语句。

我想首先检查元素,如果Popular元素为空,则将enterprisePopularName设置为空字符串

类似:

<- if((enterprise * EName * Popular)) enterprise * EName * Popular else ""      

但是我想不出来。我想这是因为我是个scala新手。

谓语回答将工作,但Seq有一个很好的小方法称为padTo,您可以使用它来确保序列中至少有n个值。它接受两个参数length: Intelem: B,其中BSeq包含的类型的子类型。所以在你的例子中应该是:

for {
  enterprise <- itr
  enterpriseName <- enterprise * EName * Legal
  enterprisePopularName <- (enterprise * EName * Popular).padTo(1, reasonableDefaultValue)
}

警告:我不熟悉'scales',所以这里的细节可能是错误的。特别是,您可能会发现:

  • *不返回Seq -它可能返回Iterable,在这种情况下,只需将Seq替换为Iterable,或者一些自定义集合,在这种情况下,您需要弄清楚如何翻译下面的方法。
  • 可能,返回的序列类型是Seq[Node]或类似的,而不是Seq[String] -您需要将默认值包装为节点,或者在应用默认值之前转换序列(使用.map(_.toString))。

我假设这里*返回某种序列(Scala的Seq)。我们需要的是一个接受Seq和默认值的方法,如果Seq为空,则产生默认值。请注意,这只是编写OptionorElsegetOrElse方法的等价物的情况。

我们可以这样做:

def orIfEmpty[A](xs : Seq[A], default : A) : Seq[A] = 
  if (xs.isEmpty) Seq(default) else xs

现在我们可以在推导式中使用:

enterprisePopularName <- orIfEmpty(enterprise * EName * Popular, "")

最新更新