如何修改PySpark的Lambda列表推导式以生成目标键值对格式?
解决PySpark生成扁平词对列表的问题
嗨,我来帮你搞定这个问题!首先咱们拆解下你遇到的两个核心问题:一是当前代码生成了嵌套列表,二是词对的逻辑不符合你的目标输出(你要的是连续相邻的词对,但原代码生成了所有两两组合的词对)。
问题根源分析
你的原lambda表达式用了两层嵌套的列表推导,返回的是「列表的列表」,比如对["This","is","first"]会生成[[((This,is),1), ((This,first),1)], [((is,first),1)]],这会导致flatMap处理后仍有嵌套结构;同时原逻辑生成了所有i<j的词对(比如(This,first)),这不是你想要的结果。
修改方案
我们需要做两个调整:
- 把词对逻辑改成连续相邻的词对(只取
i和i+1位置的单词); - 让lambda返回扁平的可迭代对象(去掉内层列表,用单层列表或生成器表达式)。
修改后的代码如下:
# 用单层列表推导,生成连续相邻词对 couples = lines.map(lambda s : s.split(" ")).flatMap(lambda s: [((s[i], s[i+1]), 1) for i in range(len(s)-1)])
如果想更高效(避免创建中间列表),可以用生成器表达式:
couples = lines.map(lambda s : s.split(" ")).flatMap(lambda s: (((s[i], s[i+1]), 1) for i in range(len(s)-1)))
验证效果
- 对第一句
"This is first",会生成[((u'This', u'is'), 1), ((u'is', u'first'), 1)] - 对第二句
"This is second",会生成[((u'This', u'is'), 1), ((u'is', u'second'), 1)] - 经过flatMap处理后,collect()得到的结果完全符合你的目标:
[((u'This', u'is'), 1), ((u'is', u'first'), 1), ((u'This', u'is'), 1), ((u'is', u'second'), 1)]
补充:如果你确实需要所有两两组合的词对
要是你只是想解决嵌套问题,而不是词对逻辑,那可以把嵌套列表推导改成扁平的生成器表达式:
couples = lines.map(lambda s : s.split(" ")).flatMap(lambda s: ((s[i], s[j]), 1) for i in range(len(s)-1) for j in range(i+1, len(s)))
内容的提问来源于stack exchange,提问作者Er1Hall
相关产品推荐
相关产品推荐

