scala如何命令元组?

lev*_*lev 14 scala

我试图了解scala如何处理元组的排序和排序

例如,如果我得到了列表

val l = for {i <- 1 to 5} yield (-i,i*2)
Vector((-1,2), (-2,4), (-3,6), (-4,8), (-5,10))
Run Code Online (Sandbox Code Playgroud)

scala知道如何排序:

l.sorted
Vector((-5,10), (-4,8), (-3,6), (-2,4), (-1,2))
Run Code Online (Sandbox Code Playgroud)

但是元组没有'<'方法:

l.sortWith(_ < _)

error: value < is not a member of (Int, Int)
l.sortWith(_ < _)
Run Code Online (Sandbox Code Playgroud)

scala如何知道如何对这些元组进行排序?

Eas*_*sun 20

因为sorted有一个隐含的参数ord:

def sorted [B>:A](隐式ord:math.Ordering [B]):List [A]根据Ordering对此序列进行排序.

排序很稳定.也就是说,相等的元素(由lt确定)在排序序列中与原始元素中的顺序相同.

ord用于比较元素的顺序.

并且在scala.math.Ordering:中定义了隐式转换:

implicit def Tuple2[T1, T2](implicit ord1: Ordering[T1], 
                                     ord2: Ordering[T2]): Ordering[(T1, T2)]
Run Code Online (Sandbox Code Playgroud)

所以l.sorted将转变为l.sorted(scala.math.Ordering.Tuple2[Int, Int]()).

测试一下:

scala> def catchOrd[A](xs: A)(implicit ord: math.Ordering[A]) = ord
catchOrd: [A](xs: A)(implicit ord: scala.math.Ordering[A])scala.math.Ordering[A]

scala> catchOrd((1,2))
res1: scala.math.Ordering[(Int, Int)] = scala.math.Ordering$$anon$11@11bbdc80
Run Code Online (Sandbox Code Playgroud)

当然,您可以定义自己的Ordering:

scala> implicit object IntTupleOrd extends math.Ordering[(Int, Int)] {
     |   def compare(x: (Int, Int), y: (Int, Int)): Int = {
     |     println(s"Hi, I am here with x: $x, y: $y")
     |     val a = x._1*x._2
     |     val b = y._1*y._2
     |     if(a > b) 1 else if(a < b) -1 else 0
     |   }
     | }
defined object IntTupleOrd

scala> Seq((1, 10), (3, 4),  (2, 3)).sorted
Hi, I am here with x: (1,10), y: (3,4)
Hi, I am here with x: (3,4), y: (2,3)
Hi, I am here with x: (1,10), y: (2,3)
res2: Seq[(Int, Int)] = List((2,3), (1,10), (3,4))
Run Code Online (Sandbox Code Playgroud)

编辑有作一个简短的方式Tuple[Int, Int]支持所有下面的方法:<,<=,>,>=.

scala> implicit def mkOps[A](x: A)(implicit ord: math.Ordering[A]): ord.Ops =
     |   ord.mkOrderingOps(x)
mkOps: [A](x: A)(implicit ord: scala.math.Ordering[A])ord.Ops

scala> (1, 2) < (3, 4)
res0: Boolean = true

scala> (1, 2) <= (3, 4)
res1: Boolean = true

scala> (1, 2, 3) <= (1, 2, 4)
res2: Boolean = true

scala> (3, 3, 3, 3) >= (3, 3, 3, 4)
res3: Boolean = false
Run Code Online (Sandbox Code Playgroud)

  • 仅当第一个元素相等时,排序才会查看元组的第二个元素. (4认同)