我正在使用scala玩一点,我想打开一个文本文件,读取每一行并保存一些hashset中的字段。 输入文件将是这样的:
1 2 3
2 4 5
首先,我只是想将每列的第一个元素存储到一个变量中,但似乎没有任何事情发生。 我的代码是:
var id = 0
val textFile = sc.textFile(inputFile);
val nline = textFile.map(_.split(" ")).foreach(r => id = r(0))
我正在使用spark因为我想稍后处理更大量的数据,所以我试图习惯它。我正在打印id,但我只得到0 有什么想法吗?
答案 0 :(得分:1)
有几件事:
首先,在map和foreach中,您正在执行代码上运行代码。您定义的id变量位于驱动程序上。您可以使用闭包将变量传递给执行程序,但不是相反。如果您考虑一下,当您有10个执行者同时运行记录时,您希望返回哪个ID值?
编辑 - foreach是一项操作
我错误地称foreach不是下面的动作。这是一个只允许您对行运行任意代码的操作。例如,如果您有自己的代码将结果保存到其他数据存储,则非常有用。 foreach不会将任何数据带回给驱动程序,因此对您的情况没有帮助。
结束修改
其次,你调用的所有spark方法都是转换,你还没有调用一个动作。在调用动作之前,Spark实际上并不运行任何代码。相反,它只是在您指定操作之前构建要发生的转换的图形。操作是需要实现结果的东西,要么将数据提供给驱动程序,要么将它们保存在HDFS之类的某个地方。
在你的情况下,为了获得价值,你会想要使用像"收集"它将RDD中的所有值返回给驱动程序。但是,只有当您知道返回的值不是很多时,才应该这样做。如果你在1亿条记录上运行,你不想尝试将它们全部拉回给驱动程序!一般来说,您只需要在处理并减少数据后将数据拉回驱动程序。
答案 1 :(得分:0)
我只是想将每列的第一个元素存储到a 变量似乎没有发生。
val file_path = "file.txt"
val ds = ss.read.textFile(file_path)
val ar = ds.map(x => x.split(" ")).first()
val (x,y,z) = (ar(0),ar(1),ar(2))
您可以使用上面的x,y,z访问列的第一个值。 使用您的文件,x = 1,y = 2,z = 3。
val ar1 = ds.map(x => x.split(" "))
val final_ds = ar.select($"value".getItem(0).as("col1") , $"value".getItem(1).as("col2") , $"value".getItem(2).as("col3")) // you can name the columns as like this
Output :
+----+----+----+
|col1|col2|col3|
+----+----+----+
| 1| 2| 3|
| 2| 4| 5|
+----+----+----+
您可以在final_ds
上运行任何类型的sql,就像下面的小样本一样。
final_ds.select("col1","col2").where(final_ds.col("col1") > 1).show()
Output:
+----+----+
|col1|col2|
+----+----+
| 2| 4|
+----+----+