日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Scala比较器:Ordered与Ordering

發布時間:2024/4/13 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Scala比较器:Ordered与Ordering 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在項目中,我們常常會遇到排序(或比較)需求,比如:對一個Person類

case class Person(name: String, age: Int) {override def toString = {"name: " + name + ", age: " + age} }

按name值逆詞典序、age值升序做排序;在Scala中應如何實現呢?

1. 兩個特質

Scala提供兩個特質(trait)Ordered與Ordering用于比較。其中,Ordered混入(mix)Java的Comparable接口,而Ordering則混入Comparator接口。眾所周知,在Java中

  • 實現Comparable接口的類,其對象具有了可比較性;
  • 實現Comparator接口的類,則提供一個外部比較器,用于比較兩個對象。

Ordered與Ordering的區別與之相類似:

  • Ordered特質定義了相同類型間的比較方式,但這種內部比較方式是單一的;
  • Ordered則是提供比較器模板,可以自定義多種比較方式。

以下源碼分析基于Scala 2.10.5。

Ordered

Ordered特質更像是rich版的Comparable接口,除了compare方法外,更豐富了比較操作(<, >, <=, >=):

trait Ordered[T] extends Comparable[T] {def compare(that: A): Intdef < (that: A): Boolean = (this compare that) < 0def > (that: A): Boolean = (this compare that) > 0def <= (that: A): Boolean = (this compare that) <= 0def >= (that: A): Boolean = (this compare that) >= 0def compareTo(that: A): Int = compare(that) }

此外,Ordered對象提供了從T到Ordered[T]的隱式轉換(隱式參數為Ordering[T]):

object Ordered {/** Lens from `Ordering[T]` to `Ordered[T]` */implicit def orderingToOrdered[T](x: T)(implicit ord: Ordering[T]): Ordered[T] =new Ordered[T] { def compare(that: T): Int = ord.compare(x, that) } }

Ordering

Ordering,內置函數Ordering.by與Ordering.on進行自定義排序:

import scala.util.Sorting val pairs = Array(("a", 5, 2), ("c", 3, 1), ("b", 1, 3))// sort by 2nd element Sorting.quickSort(pairs)(Ordering.by[(String, Int, Int), Int](_._2))// sort by the 3rd element, then 1st Sorting.quickSort(pairs)(Ordering[(Int, String)].on(x => (x._3, x._1)))

2. 實戰

比較

對于Person類,如何做讓其對象具有可比較性呢?我們可使用Ordered對象的函數orderingToOrdered做隱式轉換,但還需要組織一個Ordering[Person]的隱式參數:

implicit object PersonOrdering extends Ordering[Person] {override def compare(p1: Person, p2: Person): Int = {p1.name == p2.name match {case false => -p1.name.compareTo(p2.name)case _ => p1.age - p2.age}} }val p1 = new Person("rain", 13) val p2 = new Person("rain", 14) import Ordered._ p1 < p2 // True

Collection Sort

在實際項目中,我們常常需要對集合進行排序?;氐介_篇的問題——如何對Person類的集合做指定排序呢?下面用List集合作為demo,探討在scala集合排序。首先,我們來看看List的sort函數:

// scala.collection.SeqLikedef sortWith(lt: (A, A) => Boolean): Repr = sorted(Ordering fromLessThan lt)def sortBy[B](f: A => B)(implicit ord: Ordering[B]): Repr = sorted(ord on f)def sorted[B >: A](implicit ord: Ordering[B]): Repr = { ... }

若調用sorted函數做排序,則需要指定Ordering隱式參數:

val p1 = new Person("rain", 24) val p2 = new Person("rain", 22) val p3 = new Person("Lily", 15) val list = List(p1, p2, p3)implicit object PersonOrdering extends Ordering[Person] {override def compare(p1: Person, p2: Person): Int = {p1.name == p2.name match {case false => -p1.name.compareTo(p2.name)case _ => p1.age - p2.age}} } list.sorted // res3: List[Person] = List(name: rain, age: 22, name: rain, age: 24, name: Lily, age: 15)

若使用sortWith,則需要定義返回值為Boolean的比較函數:

list.sortWith { (p1: Person, p2: Person) =>p1.name == p2.name match {case false => -p1.name.compareTo(p2.name) < 0case _ => p1.age - p2.age < 0} } // res4: List[Person] = List(name: rain, age: 22, name: rain, age: 24, name: Lily, age: 15)

若使用sortBy,也需要指定Ordering隱式參數:

implicit object PersonOrdering extends Ordering[Person] {override def compare(p1: Person, p2: Person): Int = {p1.name == p2.name match {case false => -p1.name.compareTo(p2.name)case _ => p1.age - p2.age}} }list.sortBy[Person](t => t)

RDD sort

RDD的sortBy函數,提供根據指定的key對RDD做全局的排序。sortBy定義如下:

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

僅需定義key的隱式轉換即可:

scala> val rdd = sc.parallelize(Array(new Person("rain", 24),new Person("rain", 22), new Person("Lily", 15)))scala> implicit object PersonOrdering extends Ordering[Person] {override def compare(p1: Person, p2: Person): Int = {p1.name == p2.name match {case false => -p1.name.compareTo(p2.name)case _ => p1.age - p2.age}}}scala> rdd.sortBy[Person](t => t).collect() // res1: Array[Person] = Array(name: rain, age: 22, name: rain, age: 24, name: Lily, age: 15)

3. 參考資料

[1] Alvin Alexander, How to sort a sequence (Seq, List, Array, Vector) in Scala.

超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生

總結

以上是生活随笔為你收集整理的Scala比较器:Ordered与Ordering的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。