Spark关于RDD的二次排序

待排序数据:

D 4
A 6
A 3
A 1
D 7
B 6
C 2

代码: 

#二次排序
from operator import gt 
from pyspark import SparkContext, SparkConf
# 定义一个类,用于排序的键(根据column1的值降序,column1的值相等根据column2的值降序)
class SecondarySortKey():
    def __init__(self, k):
        self.column1 = k[0]
        self.column2 = k[1]

    def __gt__(self, other): 
    	# 如果第一列相等,则比较第二列
        if other.column1 == self.column1:
            return gt(self.column2,other.column2)
        # 否则直接比较第一个组件
        else:
            return gt(self.column1, other.column1)

if __name__ == '__main__':
  conf = SparkConf().setAppName('spark_sort').setMaster('local[1]')
  sc = SparkContext(conf=conf)
  # 文件路径
  file="file:home/zzp/PycharmProjects/SecondarySort/file4.txt"
  # 读取文件内容,创建RDD  
  rdd1 = sc.textFile(file)
  # 过滤掉空行  
  rdd2 = rdd1.filter(lambda x: (len(x.strip()) > 0))  
  # 将每一行分割为两部分,第一部分作为键,第二部分转换为整数,并与原行一起构成元组 ((A,4),"A 4") 
  rdd3 = rdd2.map(lambda x: ((x.split(" ")[0], int(x.split(" ")[1])), x))  
  # 将键映射为自定义的SecondarySortKey对象,用于排序  x[0]=(A,4)   x[1]="A 4"
  rdd4 = rdd3.map(lambda x: ( SecondarySortKey(x[0]) , x[1]))  
  # 根据SecondarySortKey对象进行升序排序  
  rdd5 = rdd4.sortByKey()  
  # 提取排序后的值(原文件行"A 4")  
  rdd6 = rdd5.map(lambda x: x[1])  
  # 将结果保存为文本文件,这里先通过repartition(1)确保所有结果都写入同一个分区  
  rdd6.repartition(1).saveAsTextFile("file:///home/zzp/PycharmProjects/SecondarySort/result")

运行结果:

A 1
A 3
A 6
B 6
C 2
D 4
D 7

答疑解惑: 

1.这段SecondarySortKey()代码是什么意思,若接收数据为(B,6),(A,4),(A,1),说明SecondarySortKey()处理过程 ??? 

1.SecondarySortKey()是什么意思,若接收数据为(B,6),(A,4),(A,1),说明SecondarySortKey()处理过程 ???
class SecondarySortKey():
    def __init__(self, k):
        self.column1 = k[0]
        self.column2 = k[1]

    def __gt__(self, other): 
    	# 如果第一列相等,则比较第二列
        if other.column1 == self.column1:
            return gt(self.column2,other.column2)
        # 否则直接比较第一个组件
        else:
            return gt(self.column1, other.column1)


这段代码定义了一个名为SecondarySortKey的类,该类用于处理二元组的排序。其主要目的是实现一个自定义的比较方法,以根据两个组件进行排序。
__init__(self, k):这是类的构造函数,用于初始化对象。它接受一个二元组k作为输入,并将k的第一个元素存储在self.column1中,将第二个元素存储在self.column2中。
__gt__(self, other):这是一个特殊的魔法方法,用于定义“大于”操作。当使用>运算符比较两个SecondarySortKey对象时,这个方法会被调用。

如果两个对象的column1相等,则比较它们的column2。如果self.column2大于other.column2,则返回True,表示self大于other。
如果column1不相等,则直接比较column1。如果self.column1大于other.column1,则返回True。
现在,对于给定的数据(B,6), (A,4), (A,1),处理过程如下:
假设我们首先将这三个二元组转换为SecondarySortKey对象。
(B,6) 转换为 SecondarySortKey(B, 6)
(A,4) 转换为 SecondarySortKey(A, 4)
(A,1) 转换为 SecondarySortKey(A, 1)

假设我们要对这三个对象进行排序。排序算法(如Python的内置sorted函数或列表的sort方法)会使用__gt__方法来比较对象。
排序过程:
首先,(A,1) 和 (A,4) 会被比较。由于它们的column1(即第一个元素)相同(都是A),所以会比较它们的column2。由于1小于4,所以(A,1)会排在(A,4)前面。
接着,(B,6) 与已经排序好的(A,1) 和 (A,4) 比较。由于(B,6)的column1(即B)与(A,1)和(A,4)的column1(即A)不同,所以直接比较column1。由于B在字母顺序上大于A,所以(B,6)会排在(A,1)和(A,4)之后。
最后,我们已经知道(A,1)排在(A,4)前面,所以最终的排序顺序是:(A,1), (A,4), (B,6)。

2.为什么(A,1) 和 (A,4) 会被先比较,明明(B,6)是第一个数据 ???

2.为什么(A,1) 和 (A,4) 会被先比较,明明(B,6)是第一个数据 ???

在排序算法中,比较的顺序并不完全取决于数据在输入列表中的顺序。
实际上,排序算法会根据比较的结果和所使用的具体算法(例如,快速排序、归并排序、堆排序等)来决定下一步比较哪两个元素。
对于以上例子,虽然(B,6)是输入列表中的第一个数据,但在排序过程中,算法会根据比较的结果动态地选择比较的元素对。
因此,(A,1)和(A,4)可能在某个阶段被选择出来进行比较,而(B,6)则可能在稍后的阶段与其他元素进行比较。
重要的是,无论比较的顺序如何,最终的结果应该是一致的,即排序算法应该能够正确地根据__gt__方法定义的顺序对所有元素进行排序。
在这个特定的例子中,由于(A,1)和(A,4)的第一个元素相同,它们会基于第二个元素进行比较。
而(B,6)的第一个元素与它们不同,所以它会与已排序好的部分(在这里是(A,1)和(A,4))的某个元素进行比较,具体是哪个元素取决于排序算法的内部逻辑。
总的来说,虽然输入的顺序是(B,6), (A,4), (A,1),但排序算法并不保证按照这个顺序来比较元素。
算法会根据其内部逻辑和__gt__方法的比较结果来动态地决定比较的顺序,以确保最终得到一个正确的排序结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值