我有一个逐行文字的文件,如下所示:
plane
car
motorbike
truck
boat
...
我正在尝试编写一个Scala程序,该程序从文件中读取值,并将每个单词映射到(键,值)对,其中键将是一个随每个值递增的整数。我写了以下内容:
val vocabFile = sc.textFile("file:///vocab.txt")
val vocabIndex=0;
val vocabs = vocabFile.map(x => (vocabIndex+=1, x))
但是我收到以下错误:
<console>:31: error: value += is not a member of Int
val vocabs = vocabularyFile.map(x => (vocabIndex+=1, x))
预期的输出将是这样的:
(1, plane)
(2, car)
(3, motorbike)
(4, truck)
(5, boat)
....
有没有办法在没有循环的情况下直接生成这样的对?
答案 0 :(得分:3)
您可以在RDD上使用.zipWithIndex()函数。
示例:
val input = List("Boat", "Car")
sc.parallelize(input).zipWithIndex().map(_.swap)
结果:
(0,Boat)
(1,Car)
我不建议使用共享变量作为索引,因为在整个群集中保持最新是很昂贵的。
答案 1 :(得分:1)
您需要能够将新值重新分配给vocabIndex
,因此它应该是var
:
var vocabIndex = 0;
此外,Scala中的赋值会导致Unit
,而不是分配的值(如Java中)。所以你需要将代码分解为:
vocabFile.map(x => { val e = (vocabIndex, x); vocabIndex += 1; e })
编辑:由于您的vocabFile
是Spark RDD
,您将获得vocabIndex
的所有并行问题。我推荐使用@SteffenSchmitz的解决方案。
答案 2 :(得分:0)
也许你可以在使用scala distinct后使用.zipWithIndex()来确保没有重复元素:
例如:
val text = Seq(plane,car,car)
val result = text.distinct.zipWithIndex
res0: Seq[(String, Int)] = List((plane,0), (car,1))