Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Map而不是FlatMap将列表[Option[A]]转换为选项[List[A]]_List_Scala_Map_Higher Order Functions - Fatal编程技术网

使用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]()){(操作系统,运行经验)=>
为了{
s
h平面图(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