scala函数 - 它是如何工作的?

时间:2015-02-06 11:55:14

标签: scala

我是scala / java的新手,我试图理解下面的代码,它返回目录中的文件列表。 Function source

  1. 需要一个名为dir的参数 - dir一个FileFile对象的类型?

  2. 它返回一个类型为file的数组。

  3. 它在listFiles上调用方法dir

  4. 最后一行是做什么的?

    
    def getRecursiveListOfFiles(dir: File): Array[File] = {
     val these = dir.listFiles
     these ++ these.filter(_.isDirectory).flatMap(getRecursiveListOfFiles)
    }

4 个答案:

答案 0 :(得分:3)

此代码使用递归进行广度优先搜索。

File可以是文件,也可以是目录。

代码dir.listFiles列出目录中的所有文件。请记住,这将是一个文件和目录列表!

然后我们可以将最后一行分解为3个方面。这些可能很容易分开。

  1. these.filter(_.isDirectory)将返回需要搜索的目录列表。它会过滤掉文件。
  2. flatMap(getRecursiveListOfFiles)获取此目录列表,并为每个目录调用getRecursiveListOfFiles。然后,它会将这些结果展平为一个列表。
  3. ++将两个数组加在一起。我们将these添加到递归调用的结果中。
  4. flatMap是关键所在。阅读它,以及它与map功能的区别,以便完全了解正在发生的事情。

答案 1 :(得分:2)

简而言之:

 these ++ these.filter(_.isDirectory).flatMap(getRecursiveListOfFiles)

基本上是:

 val allSubDirectories:Array[Files] = these.filter(_.isDirectory)
 allSubDirectories.flatMap(getRecursiveListOfFiles)
 //i.e. for each sub-directory, again find all files in sub-directory
 these ++ (files of all sub-directories)
 //ultimately add files of sub-directory to the actual list

另一种理解的方法是:

def getAllFiles(dir: File): List[File] = {
 val these = dir.listFiles.toList
 these ::: these.filter(_.isDirectory).map(x => getAllFiles(x)).flatten
}

基本上相同的控制流,每个子目录,你得到一个所有文件的列表,然后到同一个列表,你添加子目录的文件。

答案 2 :(得分:1)

我打算试着指导您如何将此视为有人试图阅读一段未知代码。

上下文应该非常清楚File可以是常规文件或目录。它不包含文件内容,但表示文件系统中的任何条目,您可以使用其他库命令打开该文件。出于此功能的目的,File只是在它是一个目录的情况下恰好包含更多File的内容,并且可以通过listFiles: List[Files]方法访问这些内容。 。据推测,它还提供其他信息,以便getRecursiveListOfFiles的原始调用者可以对结果列表执行某些操作。

同样通过上下文,these显然是当前目录中的条目。

最后一行是最微妙的。但要将其细分,它会使theseFile中的these增加flatMap,这恰好是目录。

要解释此步骤,List[File]flatMap[B](f: File => List[B]): List[B]的签名可以被视为B,其中getRecursiveListOfFiles类型变量。在这种情况下,因为递归传递了类型File => List[File]的相同函数BFile只是flatMap(f: File => List[File]): List[File],所以我们可以想到这个特定的调用为flatMap

粗略地说,f将函数f应用于容器中的每个项目,其中map需要返回相同类型的容器。 " flat"部分只是这些单独的容器被组合而不是嵌套的事实,这是{{1}}将要做的事情。这是允许函数以递归方式添加在其子目录中找到的所有文件的原因。很漂亮。

答案 3 :(得分:0)

  1. 你所画的区别是什么? dir的类型为File

  2. 一组File s,是。

  3. 它可能隐含地将these转换为scala ListBuffer,这是令人困惑的部分(例如,它可能会导入scala.collection.JavaConversions._ - 最好使用JavaConverters,这会使转化显式调用.asScalaasJava)。您可以在the scaladoc中找到++filterflatMap的定义,这有助于了解发生了什么。

  4. (注意:我的4.因为降价而成为3.()