如何在Scala中排序整数元组列表

时间:2014-12-26 16:40:43

标签: scala sorting

我有一个整数元组列表

List[(Int, Int, Int)] = List((2,1,3), (4,2,6), (4,7,9), (6,3,9), (6,7,11),
          (6,17,19), (8,4,12), (8,14,18), (10,5,15), (12,1,17), (12,6,18))

并且我想通过增加c来对它们进行排序,但是如果有相同c的元组则通过增加b来对它们进行排序。因此,在这种情况下,(4,7,9),(6,3,9)的情况我喜欢(6,3,9),(4,7,9)。

不幸的是,我所做的并不奏效。

     def order(k: List[(Int, Int, Int)]) = {
        var t = List[Int]()
        if (k.map(_._3) == t) {
            k.sortBy(_._2)
            t = k.map(_._3)
            k
        } else {
            k.sortBy(_._3)
            t = k.map(_._3)
            k
        }   
     }

提前谢谢!

3 个答案:

答案 0 :(得分:6)

一种相当简单且令人惊讶的快速方法是使用稳定的排序算法,首先按第一个组件排序,然后按第二个组件排序,然后排序第三个组件。 由于您按第三个组件排序,因此这将占主导地位。使用稳定排序时,最后一个组件中绑定的对象将按前一个排序:

Sorting.stableSort(k, (x, y) => x._1 < y._1)
Sorting.stableSort(k, (x, y) => x._2 < y._2)
Sorting.stableSort(k, (x, y) => x._3 < y._3)

或等效(但可能更昂贵,因为它构建了一系列键):

Sorting.stableSort(k, x => x._1)
Sorting.stableSort(k, x => x._2)
Sorting.stableSort(k, x => x._3)

(假设Seq.sortBy不稳定。)

或者(这是更经典和明显的方法),编写一个比较器(Ordering)使用第三个组件如果不同,那么第二个如果不同< / em>最后是第一个。这可能不是非常&#34; scalish&#34;,但它是恕我直言,非常干净,可以理解:

val result = intOrdering.compare(x._3, y._3)
if (result == 0) result = intOrdering.compare(x._2, y._2)
if (result == 0) result = intOrdering.compare(x._1, y._1)
result

再次,您也可以使用键功能(但这需要2倍的内存):

k.sortBy(x => (x._3, x._2, x._1))

答案 1 :(得分:5)

似乎

k.sortBy(x => (x._3 , x._2))

完成工作并返回

List[(Int, Int, Int)] = List((2,1,3), (4,2,6), (6,3,9), (4,7,9), (6,7,11),
          (8,4,12), (10,5,15), (12,1,17), (12,6,18), (8,14,18), (6,17,19))

也适用于(12,6,18),(8,14,18)

答案 2 :(得分:1)

您可以提供自己的Ordering[Tuple3[Int, Int, Int]],然后在sorted上使用List。例如,此处类似于Ordering上的标准Tuple3,除了纵坐标上的排序相反。对于任何(a, b, c)c的优先级高于bb的优先级高于a。你没有真正提到如何处理a,所以如果你不关心它,你可以删除相关的行。

val list = List((2,1,3), (4,2,6), (4,7,9), (6,3,9), (6,7,11), (6,17,19), (8,4,12), (8,14,18), (10,5,15), (12,1,17), (12,6,18))

implicit def t3Ordering(implicit intOrdering: Ordering[Int]) = new Ordering[Tuple3[Int, Int, Int]] {
    def compare(x: (Int, Int, Int), y: (Int, Int, Int)): Int = {
        val compare3 = intOrdering.compare(x._3, y._3)
        if (compare3 != 0) return compare3
        val compare2 = intOrdering.compare(x._2, y._2)
        if (compare2 != 0) return compare2
        val compare1 = intOrdering.compare(x._1, y._1)
        if (compare1 != 0) return compare1
        0
    }
}

scala> list.sorted
res0: List[(Int, Int, Int)] = List((2,1,3), (4,2,6), (6,3,9), (4,7,9), (6,7,11), (8,4,12), (10,5,15), (12,1,17), (12,6,18), (8,14,18), (6,17,19))

或者更一般地反转基于Tuple纵坐标的排序(对于Tuple3):

implicit def t3Ordering[T1, T2, T3](implicit ord1: Ordering[T1], ord2: Ordering[T2], ord3: Ordering[T3]) = 
  new Ordering[Tuple3[T1, T2, T3]] {
    def compare(x: (T1, T2, T3), y: (T1, T2, T3)): Int = {
        val compare3 = ord3.compare(x._3, y._3)
        if (compare3 != 0) return compare3
        val compare2 = ord2.compare(x._2, y._2)
        if (compare2 != 0) return compare2
        val compare1 = ord1.compare(x._1, y._1)
        if (compare1 != 0) return compare1
        0
    }
  }

基于standard library Ordering