使用Scala生成简单密钥

时间:2017-05-23 16:17:37

标签: scala apache-spark rdd

我有一个逐行文字的文件,如下所示:

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)
....

有没有办法在没有循环的情况下直接生成这样的对?

3 个答案:

答案 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))