Scala-在foreach循环外列出变量

时间:2018-12-06 17:42:09

标签: scala apache-spark

下面的代码没有给我想要的输出。我将finallist的输出作为单个字符并用逗号分隔;我期待的列表中只有两个值(文件名,sizeofcolumn)。

val pathurl="adl://*****.azuredatalakestore.net/<folder>/<sub_folder>"
val filelist=dbutils.fs.ls(pathurl)

val newdf = df.select("path").rdd.map(r => r(0)).collect.toList

var finallist = scala.collection.mutable.ListBuffer.empty[Any]

newdf.foreach(f => {
    val MasterPq = spark.read.option("header","true").option("inferSchema","true").parquet(f.toString())
    val size = MasterPq.columns.length
    val mergedlist = List(f.toString(), size.toString())

    mergedlist.map((x => {finallist = finallist ++ x}))

})

println(finallist)

1 个答案:

答案 0 :(得分:2)

代码中的错误是您正在使用++方法将值追加到列表中。此方法用于附加两个列表。

scala> List(1, 2) ++ List(3, 4)
res0: List[Int] = List(1, 2, 3, 4)

在scala中,字符串被视为一个字符列表,因此您将每个单独的字符追加到列表中。

scala> List(1, 2) ++ "Hello"
res3: List[AnyVal] = List(1, 2, H, e, l, l, o)

由于使用的是可变列表,因此可以使用'+ ='方法附加值。如果您只想使代码正常工作,那么下面的内容就足够了,但这不是一个很好的解决方案。

// mergedlist.map((x => {finallist = finallist ++ x}))
mergedlist.map((x => finallist += x}))

您可能是scala的新手,它来自Java之类的命令性语言。正如您从此类编程语言所知,Scala集合不起作用。默认情况下,Scala的集合是不可变的。无需修改集合,而是使用诸如map之类的功能基于旧列表构建新列表。

map函数是列表上最常用的函数之一。它采用匿名函数作为参数,该参数采用一个元素并将其转换为另一个值。此功能将应用于列表的所有方法,从而建立一个新列表。这是一个示例:

scala> val list = List(1, 2, 3).map(i => i * 2)
list: List[Int] = List(2, 4, 6)

在此示例中,将整数乘以2的函数应用于列表中的每个元素。结果将放入新列表中。也许此插图有助于理解该过程:

List(1,    2,    3)
     |     |     |
    * 2   * 2   * 2
     ↓     ↓     ↓
List(2,    4,    6)

我们可以使用map函数来解决您的任务。 我们可以使用它将newdf列表中的每个元素映射到具有相应(filename, filesize)的元组。

val finallist = newdf.map { f => 
    val masterPq = spark.read.option("header","true").option("inferSchema","true").parquet(f.toString())
    val size = masterPq.columns.length
    (f.toString(), size.toString())
}

我认为这段代码更短,更简单,更易于阅读,并且更漂亮。我肯定会建议您进一步了解Scala的收藏和不可变的收藏。一旦了解了它们,便会爱上它们!