scala集合排序
Problem
????你想要對一個集合元素進行排序。或者你想定義一個自定義類來實現Ordered trait,來讓你可以使用sorted方法,或者使用比較操符<,<=,>,>=來對類的實例進行比較。
Solution
????你可以使用sorted或者sortWith方法來對集合進行排序。
????Sorted方法可以對集合元素類型為Double,Float,Int和其他可以隱試轉化scala.math.Ordering的進行排序。
scala>?val?l?=?List(10,?5,?8,?1,?7).sorted l:?List[Int]?=?List(1,?5,?7,?8,?10)scala>?val?b?=?List("banana",?"pear",?"apple",?"orange").sorted b:?List[String]?=?List(apple,?banana,?orange,?pear)????Rich版本的numeric類(比如RichInt)和StringOps類都實現了Ordered trait,所以他們可以使用sorted方法實現排序。
????SortWith方法讓你可以使用自己的排序邏輯來實現排序規則。下面的例子展示了如何對集合元素類型為Int和String使用sortWith排序:
scala>?List(10,?5,?8,?1,?7).sortWith(_?<?_) res14:?List[Int]?=?List(1,?5,?7,?8,?10)scala>?List(10,?5,?8,?1,?7).sortWith(_?>?_) res15:?List[Int]?=?List(10,?8,?7,?5,?1)scala>?List("banana",?"pear",?"apple",?"orange").sortWith(_?<?_) res16:?List[String]?=?List(apple,?banana,?orange,?pear)scala>??List("banana",?"pear",?"apple",?"orange").sortWith(_?>?_) res17:?List[String]?=?List(pear,?orange,?banana,?apple)????你的排序方法的復雜度取決于你的排序需求。舉個例子,你可以通過sort訪問元素的方法,比如下面這個例子,按長度對一個字符串集合進行排序:
scala>?List("banana",?"pear",?"apple",?"orange").sortWith(_.length?<?_.length) res18:?List[String]?=?List(pear,?apple,?banana,?orange)scala>?List("banana",?"pear",?"apple",?"orange").sortWith(_.length?>?_.length) res19:?List[String]?=?List(banana,?orange,?apple,?pear)????如果你的排序方法非常復雜或者會被重復使用,那么你可以先定義這個方法后,再調用此方法:
scala>?def?sortByLength(s1:?String,?s2:?String)?=?{|???println("compare?%s?and?%s".format(s1,?s2))|???s1.length?>?s2.length|?} sortByLength:?(s1:?String,?s2:?String)Booleanscala>?List("banana",?"pear",?"apple").sortWith(sortByLength) compare?pear?and?banana compare?banana?and?pear compare?apple?and?pear compare?apple?and?pear compare?apple?and?banana compare?banana?and?apple res20:?List[String]?=?List(banana,?apple,?pear)Discussion
????如果你定義的類,沒有定義對Ordering的隱式轉換,那么你就沒有辦法通過調用sorted方法來對集合元素進行排序。
scala>?class?Person(var?name:?String)?{|???override?def?toString?=?name|?} defined?class?Person????創建一個Person集合:
scala>?val?ty?=?new?Person("Tyler") ty:?Person?=?Tylerscala>?val?al?=?new?Person("Al") al:?Person?=?Alscala>?val?paul?=?new?Person("Paul") paul:?Person?=?Paulscala>?val?dudes?=?List(ty,?al,?paul) dudes:?List[Person]?=?List(Tyler,?Al,?Paul)????如果你調用sorted方法對dudes進行排序,那么你會看到下面的錯誤提示:
scala>?dudes.sorted <console>:13:?error:?No?implicit?Ordering?defined?for?Person.dudes.sorted^????但是你可以使用sortWith對dudes進行排序:
scala>?dudes.sortWith(_.name?<?_.name) res1:?List[Person]?=?List(Al,?Paul,?Tyler)scala>?dudes.sortWith(_.name?>?_.name) res2:?List[Person]?=?List(Tyler,?Paul,?Al)Mix in the Ordered trait
????混入Ordered特質能夠讓你的程序使用sorted方法來對Person集合進行排序,但是你必須實現compare方法。
class?Person(var?name:?String)?extends?Ordered[Person]{override?def?toString?=?nameoverride?def?compare(that:?Person):?Int?=?{if?(this.name?==?that.name)?return?0else?if?(this.name?>?that.name)?return?1else?return?-1} }????這個新的Person類就可以使用sorted方法來進行排序了。
????Compare方法提供了排序功能,compare方法會這樣進行工作:
-
如果兩個對象相等,返回0
-
如果this<that那么返回一個負數
-
如果shit>that那么返回一個正數
????類的兩個實例誰大誰小完全取決于你的compare算法,因為目前這個算法僅僅比較兩個字符串的值,所以也可以寫成這樣:
????使用Ordered特質的另外一個好處是它可以讓你在代碼中直接比較對象實例。
if?(al?>?ty)?println("Al")?else?println("Tyler")????上面代碼之所以可以工作是因為Ordered特質實現了<=, <, >, >=方法,并調用你定義的compare方法來使之生效。
See Also
For more information, the Ordered and Ordering Scaladoc is excellent, with good examples of this approach, and other approaches.
? The Ordering trait
? The Ordered trait
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
- 上一篇: scala创建并使用Enumeratio
- 下一篇: scala通过mkString方法把一个