Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.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
从列表中筛选项目并在Scala中计数的惯用方法是什么_Scala_Apache Spark_Functional Programming - Fatal编程技术网

从列表中筛选项目并在Scala中计数的惯用方法是什么

从列表中筛选项目并在Scala中计数的惯用方法是什么,scala,apache-spark,functional-programming,Scala,Apache Spark,Functional Programming,我发现我经常会得到一个选项列表(或是一个选项或一个选项),我想在我把列表展平之前数一数没有选项的数目。有没有一种很好的惯用方法,不需要我多次处理列表 类似这样但更好的东西: val sprockets: List[Option[Sprockets]] = getSprockets() println("this many sprockets failed to be parsed" + sprockets.filter(_.isEmpty).count) println(sprockets.f

我发现我经常会得到一个选项列表(或是一个选项或一个选项),我想在我把列表展平之前数一数没有选项的数目。有没有一种很好的惯用方法,不需要我多次处理列表

类似这样但更好的东西:

val sprockets: List[Option[Sprockets]] = getSprockets()
println("this many sprockets failed to be parsed" + sprockets.filter(_.isEmpty).count) 
println(sprockets.flatten)

这就是你要找的吗

val foo = List(Some(3), Some(4), None:Option[Int], Some(5), Some(6))
val (concatenatedList, emptyCount) =
  foo.map(entry =>
      (entry.toList, if (entry.isEmpty) 1 else 0)
  ).fold((List[Int](), 0))((a, b) =>
      (a._1 ++ b._1, a._2 + b._2)
  )
这是一个过程,但我不确定它是否真的比两个过程更有效——在这种情况下,额外的对象创建(Tuple2s)将抵消两个过程中的额外循环。

递归可能吗

 @tailrec
 def flattenAndCountNones[A](in: Seq[Option[A]], out: Seq[A] = Queue.empty[A], n: Int = 0): (Seq[A], Int) = in match {
   case Nil => (out, n)
   case Some(x) :: tail => flattenAndCountNones(tail, out :+ x, n)
   case None :: tail => flattenAndCountNones(tail, out, n + 1) 
 }

我会使用Daenyth建议的折叠,例如这样的东西:

  val list = List(Some(1),None,Some(0),Some(3),None)

  val (flatList,count) = list.foldLeft((List[Int](),0)){
    case ((data,count), Some(x)) => (data :+ x, count)
    case ((data,count), None) => (data, count +1)
  }

  //output
  //flatList: List[Int] = List(1, 0, 3)
  //count: Int = 2

如果您一次就需要它,您可以
折叠
。或者,您可以使用
链轮。计数
,并将其与
链轮进行比较。展平。计数
?为什么您认为过滤器和计数不是惯用方法?正如@Daenyth所说,在标准的Scala操作符中,折叠是您在一次传递中完成此操作的最佳选择。一般来说,您可能正在寻找与
mapAccum
或的等效项。