模式匹配树状选项结构的更好实现

时间:2015-05-11 07:06:07

标签: scala pattern-matching tuples scala-option

  def leadParser(optionTuples: Option[(Option[(Option[(Option[(Option[(
                                Option[Iterable[EmailLead]],
                                Option[Iterable[QuestionLead]])],
                                Option[Iterable[LocalMarketQuestionLead]])],
                                Option[Iterable[OfferLead]])],
                                Option[Iterable[Bid]])],
                                Option[Iterable[CreditApplicationLeadWithEbayId]])]) = {
    optionTuples match{
      case None => (None, None, None, None, None, None)
      case Some(c) =>
        val creditApplictaionIteratorOption = c._2
        c._1 match {
          case None => (None, None, None, None, None, creditApplictaionIteratorOption)
          case Some(b) =>
            val bidIteratorOption = b._2
            b._1 match {
              case None => (None, None, None, None, bidIteratorOption, creditApplictaionIteratorOption)
              case Some(o) =>
                val offerIteratorOption = o._2
                o._1 match {
                  case None => (None, None, None, offerIteratorOption, bidIteratorOption, creditApplictaionIteratorOption)
                  case Some(l) =>
                    val localMarketQuestionIteratorOption = l._2
                    l._1 match {
                      case None => (None, None, localMarketQuestionIteratorOption, offerIteratorOption, bidIteratorOption, creditApplictaionIteratorOption)
                      case Some(q) =>
                        val questionIteratorOption = q._2
                        val emailIteratorOption = q._1
                        (emailIteratorOption, questionIteratorOption, localMarketQuestionIteratorOption, offerIteratorOption, bidIteratorOption, creditApplictaionIteratorOption)
                        }
                    }
                }
            }
        }
}

我知道输入选项[...看起来很疯狂,但这是我从Spark操作中得到的,所以我必须处理它。有没有更好的方法从这个复杂的元组/选项结构中获取所有迭代器选项?

1 个答案:

答案 0 :(得分:2)

您可以使用模式匹配来声明变量,而不仅仅是在case语句中。这解锁了几种非嵌套的可能性,这些可能性更具可读性。例如:

def leadParser(optionTuples: Option[(Option[(Option[(Option[(Option[(Option[Iterable[EmailLead]],Option[Iterable[QuestionLead]])],Option[Iterable[LocalMarketQuestionLead]])],Option[Iterable[OfferLead]])],Option[Iterable[Bid]])],Option[Iterable[CreditApplicationLeadWithEbayId]])]) = {
    val (creditRest, credit) = optionTuples.getOrElse(None -> None)
    val (bidRest, bid) = creditRest.getOrElse(None -> None)
    val (offerRest, offer) = bidRest.getOrElse(None -> None)
    val (localRest, local) = offerRest.getOrElse(None -> None)
    val (email, question) = localRest.getOrElse(None -> None)
    (credit, bid, offer, local, email, question)
}

这里我们在每个连续嵌套的getOrElse上使用Option来封装回退值。

模式匹配语法(在变量声明和match子句中)可以嵌套以考虑内部结构。这给了你另一种可能性:

def leadParser(optionTuples: Option[(Option[(Option[(Option[(Option[(Option[Iterable[EmailLead]],Option[Iterable[QuestionLead]])],Option[Iterable[LocalMarketQuestionLead]])],Option[Iterable[OfferLead]])],Option[Iterable[Bid]])],Option[Iterable[CreditApplicationLeadWithEbayId]])]) = {
    optionTuples match {
        case Some((Some((Some((Some((Some((a, b)), c)), d)), e)), f)) => (a, b, c, d, e, f)
        case Some((Some((Some((Some((None, c)), d)), e)), f)) => (None, None, c, d, e, f)
        case Some((Some((Some((None, d)), e)), f)) => (None, None, None, d, e, f)
        case Some((Some((None, e)), f)) => (None, None, None, None, e, f)
        case Some((None, f)) => (None, None, None, None, None, f)
        case None => (None, None, None, None, None, None)
    }
}

这里我们使用几个嵌套模式匹配来捕获复数值的内部结构。

这里的其他自然选择是某种阻止嵌套的for理解,或者是一种使这种类型的可选元组变平的泛型递归函数。最后,如果这太麻烦,您可能会考虑使用像Shapeless这样的库,可能会让您更简洁地使用这种复杂类型。不过,我认为那会有点矫枉过正。