加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

如何编写在Scala中返回Option [List]的函数?

发布时间:2020-12-16 09:28:30 所属栏目:安全 来源:网络整理
导读:假设我有两个函数来获取订单和订单商品: def getOrders(): Option[List[Int]] = ...def getOrderItems(orderId: Int): Option[List[Int]] = ... 请注意,由于每个函数都可能失败,因此两个函数都返回Option [List]. 现在我想获得所有订单商品的清单选项,如下
假设我有两个函数来获取订单和订单商品:

def getOrders(): Option[List[Int]] = ...
def getOrderItems(orderId: Int): Option[List[Int]] = ...

请注意,由于每个函数都可能失败,因此两个函数都返回Option [List].

现在我想获得所有订单商品的清单选项,如下所示:

>如果两个函数都返回Some和,则返回一些[List]
>如果其中任何一个返回None,则为None.

我尝试用for(参见下文)编写这些函数,但它不起作用.

val allOrderItems = for {
  orderIds   <- getOrders();
  orderId    <- orderIds;
  orderItems <- getOrderItems(orderId)
} yield orderItems

如何使用函数getOrders和getOrderItems构建函数getAllOrderItems():Option [List [Int]]?

解决方法

你真的希望能够将选项[List [Option [List [Int]]]]的中间两层内部翻出来,这样你就可以得到彼此相邻的选项和列表.此操作称为排序,由Scalaz提供:

import scalaz._,Scalaz._

val items: Option[List[Int]] =
  getOrders.flatMap(_.map(getOrderItems).sequence).map(_.flatten)

你可以等效地使用traverse,它结合了map和sequence操作:

val items: Option[List[Int]] =
  getOrders.flatMap(_ traverse getOrderItems).map(_.flatten)

如果您不想使用Scalaz,您可以编写自己的(更少多态)序列:

def sequence[A](xs: List[Option[A]]) = xs.foldRight(Some(Nil): Option[List[A]]) {
  case (Some(h),Some(t)) => Some(h :: t)
  case _ => None
}

接着:

val items: Option[List[Int]] = getOrders.flatMap(
  orderIds => sequence(orderIds.map(getOrderItems))
).map(_.flatten)

monad转换解决方案实际上也非常简单(如果您愿意使用Scalaz):

val items: Option[List[Int]] = (
  for {
    orderId <- ListT(getOrders)
    itemId  <- ListT(getOrderItems(orderId))
  } yield itemId
).underlying

这种方法的好处在于你不必考虑你需要压扁,顺序等等 – 普通的monadic操作完全符合你的要求.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读