如何在PySpark中从RDD创建键值对及对应Scala代码改写
PySpark 改写Scala版字符串数组转PairRDD实现
原Scala代码逻辑拆解
原代码的处理流程共3个核心步骤:
- 逐行将字符串按
,(逗号+空格)分割为数组 - 取每个数组的首个元素作为键,剩余元素每2个分为一组,取每组第一个元素作为值
- 将所有分组生成的键值对展平,得到最终的PairRDD
对应PySpark实现代码
直接用Python的lambda表达式和列表切片就能完全对齐原逻辑,代码如下:
pair_rdd = rdd.map(lambda line: line.split(", ")) \ .flatMap(lambda arr: [(arr[0], val) for val in arr[1::2]])
代码对应关系说明
lambda line: line.split(", "):和Scala的_.split(", ")完全等价,负责逐行切分字符串得到列表arr[0]:等价于Scala的x.head,取切分后列表的第一个元素作为键arr[1::2]:等价于Scala的x.tail.grouped(2).map(y => y.head):arr[1:]对应x.tail,取除首元素外的所有剩余元素- 切片步长设为2,即从剩余元素的第一个位置开始,每2个元素取第一个,正好对应分组后取组首元素的逻辑
- 列表推导式生成所有(键, 值)元组,交给
flatMap展平,和原Scala的flatMap处理逻辑完全一致
效果验证样例
如果输入RDD内容如下:
rdd = sc.parallelize([ "class1, zhangsan, 90, lisi, 85, wangwu, 92", "class2, zhaoliu, 78, sunqi, 88" ])
运行上述代码后,最终输出的PairRDD结果为:
[ ('class1', 'zhangsan'), ('class1', 'lisi'), ('class1', 'wangwu'), ('class2', 'zhaoliu'), ('class2', 'sunqi') ]
和原Scala代码执行结果完全一致。
注意:如果输入行存在格式异常(比如切分后长度不足2),会触发索引越界错误,可根据业务需求在map/flatMap阶段增加长度校验逻辑。
内容的提问来源于stack exchange,提问作者Kevin Tracey
相关产品推荐
相关产品推荐

