2017-04-22 56 views
3

如何使用Spark-Scala中的takeOrdered(4)(Ordering[Int])方法對2列或多列進行排序。如何使用takeOrdered對多個列進行排序?

此使用sortBy這樣我可以實現:

lines.sortBy(x => (x.split(",")(1).toInt, -x.split(",")(4).toInt)).map(p => println(p)).take(50) 

但是當我嘗試使用takeOrdered接近其未能

+0

'線條'的類型是什麼? –

回答

0

排序您可以實現自定義排序:

lines.takeOrdered(4)(new Ordering[String] { 
    override def compare(x: String, y: String): Int = { 
    val xs=x.split(",") 
    val ys=y.split(",") 
    val d1 = xs(1).toInt - ys(1).toInt 
    if (d1 != 0) d1 else ys(4).toInt - xs(4).toInt 
    } 
}) 
1

tl; dr做一些這樣的事情(但是考慮重寫你的代碼來調用split一次):

lines.map(x => (x.split(",")(1).toInt, -x.split(",")(4).toInt)).takeOrdered(50) 

這裏是解釋。

當你調用takeOrdered直接lines,生效的implicit OrderingOrdering[String]因爲linesRDD[String]。您需要將lines轉換爲新的RDD[(Int, Int)]。因爲有implicit Ordering[(Int, Int)]可用,它會在您的轉換RDD上生效。

同時,sortBy的工作原理有所不同。下面是簽名:

sortBy[K](f: (T) ⇒ K, ascending: Boolean = true, numPartitions: Int = this.partitions.length)(implicit ord: Ordering[K], ctag: ClassTag[K]): RDD[T] 

我知道這是一個令人生畏的簽名,但如果你通過削減噪音,你可以看到sortBy需要您的原始類型映射到一個新的類型只是排序目的的功能,如果其中一個在implicit範圍內,則適用於該返回類型的Ordering

在你的情況,你在你的RDD應用功能的String s到它們轉變成如何星火應該僅僅把它們用於排序目的「視圖」,(Int, Int),然後依靠implicit Ordering[(Int, Int)]如上所述可用。

sortBy方法可以讓你保持lines完整爲RDD[String]和使用映射只是進行排序,而takeOrdered方法上全新RDD,包含從原始lines衍生(Int, Int)工作。哪種方法更適合您的需求取決於您希望完成什麼。

在另一個說明中,您可能想要將您的代碼重寫爲只有split您的文本一次。