使用Map而不是FlatMap将列表[Option[A]]转换为选项[List[A]]
书中有一个问题,要求将选项列表转换为列表选项。函数签名如下:使用Map而不是FlatMap将列表[Option[A]]转换为选项[List[A]],list,scala,map,higher-order-functions,List,Scala,Map,Higher Order Functions,书中有一个问题,要求将选项列表转换为列表选项。函数签名如下: def sequence[A](a:List[Option[A]]):Option[List[A]] def sequence[A](a:List[Option[A]]):Option[List[A]] = a match { case Nil => Some(Nil) case h::t => h flatMap (r => sequence(t) map (h::_)) } 在该书的网站上,该功能
def sequence[A](a:List[Option[A]]):Option[List[A]]
def sequence[A](a:List[Option[A]]):Option[List[A]] = a match {
case Nil => Some(Nil)
case h::t => h flatMap (r => sequence(t) map (h::_))
}
在该书的网站上,该功能的实现如下:
def sequence[A](a:List[Option[A]]):Option[List[A]]
def sequence[A](a:List[Option[A]]):Option[List[A]] = a match {
case Nil => Some(Nil)
case h::t => h flatMap (r => sequence(t) map (h::_))
}
我对h平面图(r=>sequence(t)map(h::))
部分有点困惑。如果我把它分解,它是这样的:
h属于选项[A]
类型。在h上执行flatMap将返回一个选项[B]
,但它将一个函数f作为参数,该函数将a作为参数并返回一个选项[B]
,现在在上面的示例中,序列(t)映射(h::)
将返回一个与函数的返回类型一致的选项[List[a]
是否可以使用map代替flatMap来执行从List[Option[A]]
到Option[List[A]]
的转换?此外,提供的解决方案似乎不是尾部递归的。是否可以使尾部递归?有一个输入错误:
case h::t => h flatMap (r => sequence(t) map (h::_))
应该有r::
或h.toList::
,而不是h:
sequence(t)
返回选项[List[A]]
<代码>映射(r::)在选项[List[A]]
上不要更改类型。它只需从选项
中获取一个列表[a]
,如果有的话,并在其前面加上a
因此,sequence(t)map(r::)
的类型是Option[List[A]]
您不需要flatMap
此处:
def sequence[A](a:List[Option[A]]):Option[List[A]] = a match {
case Nil => Some(Nil)
case None :: _ => None
case Some(r) :: t => sequence(t) map (r :: _)
}
解决方案可以是尾部递归的。尾部递归和List
的常见问题是,最后必须反转列表:
def sequence[A](a:List[Option[A]]):Option[List[A]] = {
@tailrec def loop(a: List[Option[A]], subres: List[A] = Nil): Option[List[A]] =
a match {
case Nil => Some(subres)
case None :: _ => None
case Some(r) :: t => loop(t, r :: subres)
}
loop(a) map {_.reverse}
}
事实上,它可以完全不递归:
def sequence[A](a:List[Option[A]]):Option[List[A]] =
a.foldLeft(Option(List[A]())){ (os, oe) =>
for {
s <- os
e <- oe
} yield e :: s
}.map{ _.reverse }
def序列[A](A:List[Option[A]]:Option[List[A]]=
a、 foldLeft(选项(列表[a]()){(操作系统,运行经验)=>
为了{
sh平面图(r=>sequence(t)map(h::)))
应该是h平面图(r=>sequence(t)map(r:)))
,因为h
是类型选项[A]
的,而r
是类型A
的。我们正试图将元素附加到映射中的类型列表[A]
不使用递归的另一种解决方案是:
def sequence[A](a: List[Option[A]])(implicit nullValue: A):Option[List[A]] = {
Option(a map { x => x.getOrElse(nullValue)})
}
我找到了另一种实现seq函数的方法,它没有隐式使用递归:
def seq[A](a: List[Option[A]]):Option[List[A]] = a.foldLeft(Some(Nil):Option[List[A]])((collected,elem) => elem.flatMap(el=> collected.map(el::_)))
nullValue
取决于当元素为None
时用户希望放入列表中的内容。例如:序列(列表(一些(1),一些(2),无))(-1)
。如果用户希望省略None
,那么问题中的另一个issuemethod序列
将返回None
,如果不是源集合的所有元素都是Some
。它的工作原理类似于If(a.forall(.isDefined))Some(a.map{uu.get})else None
@senia Oh ok。谢谢。那是我的错。我在None的情况下添加了一个默认值。一个映射{uu.getOrElse(默认)}
更短。第二个解决方案不适用于序列(列表(一些(1),一些(2),没有))
。它返回None