我对spark-scala相当新,所以请不要介意这是否是一个初学者问题。
我有一个目录测试,其中包含两个文件input1.txt和input2.txt。 现在,假设我使用
创建一个名为inputRDD的RDDval inputRDD = sc.wholeTextFiles("/home/hduser/test")
将两个文件都包含在RDD(inputRDD)对中。
根据我的理解,inputRDD包含文件名作为键,内容作为值 像这样的东西
(input1.txt,contents of input1.txt)
(input2.txt,contents of input2.txt)
现在,假设我必须基于第一列以这种方式(在同一个RDD中)对这两个文件执行连接。
contents of input1.txt ---------------------- 1 a 1 b 2 c 2 d contents of input2.txt ---------------------- 1 e 2 f 3 g
我该怎么做?
答案 0 :(得分:0)
您需要首先拆分内容,然后执行reduceByKey
格式化您的加入。如下所示:
val outputRDD = inputRDD.mapPartitions(iter => {
iter.map(path_content => {
// split string content
val splittedStr = path_content._2.split(" ")
// outputs (1, a) (1, b) (2, c)
(splittedStr(0), splittedStr(1))
})
}).reduceByKey(_ + _) // this outputs (1, abe)
答案 1 :(得分:0)
如果test
目录中只有两个文件,并且文件名已知,那么您可以将两个文件的文本分成两个rdds
并使用join
,如下所示
val rdd1 = inputRDD.filter(tuple => tuple._1.contains("input1.txt"))
.flatMap(tuple => tuple._2.split("\n"))
.map(line => line.split(" "))
.map(array => (array(0), array(1)))
val rdd2 = inputRDD.filter(tuple => tuple._1.contains("input2.txt"))
.flatMap(tuple => tuple._2.split("\n"))
.map(line => line.split(" "))
.map(array => (array(0), array(1)))
rdd1.join(rdd2).foreach(println)
您应该输出
(2,(c,f))
(2,(d,f))
(1,(a,e))
(1,(b,e))
我希望这是你想要的
<强>更新强>
如果test
目录中有两个名称未知的文件,则可以避免使用wholeTextFile
api并使用textFile
api将其作为单独的rdds
和{{ 1}}他们如上所述。但为此你必须编写一个列出文件的函数。
join