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

时间:2021-07-22 19:37:12
  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)
                        }
                    }
                }
            }
        }
}

I know the input Option[... looks insane but this is what I receive from a Spark operation so I have to deal with it. Could there be a better way of getting all the Iterator Options from this complicated tuple/option structure ?

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

1 个解决方案

#1


You can use pattern matching to declare variables, not just in case statements. This unlocks several non-nesting possibilities that will be more readable. For example:

您可以使用模式匹配来声明变量,而不仅仅是在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)
}

Here we've used getOrElse on each successively nested Option in order to encapsulate the fallback values.

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

The pattern matching syntax (in both variable declaration and match clauses) can be nested to account for internal structure. That gives you another possibility:

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

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)
    }
}

Here we use several nested pattern matches to capture the internal structure of the complex value.

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

The other natural choices here would be some sort of for comprehension that prevents nesting, or a generic recursive function that flattens this type of optional tuple. Finally, if this is too cumbersome, you might consider using a library like Shapeless, might allow you to work with this complex type more concisely. I think that would be overkill, though.

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

#1


You can use pattern matching to declare variables, not just in case statements. This unlocks several non-nesting possibilities that will be more readable. For example:

您可以使用模式匹配来声明变量,而不仅仅是在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)
}

Here we've used getOrElse on each successively nested Option in order to encapsulate the fallback values.

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

The pattern matching syntax (in both variable declaration and match clauses) can be nested to account for internal structure. That gives you another possibility:

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

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)
    }
}

Here we use several nested pattern matches to capture the internal structure of the complex value.

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

The other natural choices here would be some sort of for comprehension that prevents nesting, or a generic recursive function that flattens this type of optional tuple. Finally, if this is too cumbersome, you might consider using a library like Shapeless, might allow you to work with this complex type more concisely. I think that would be overkill, though.

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