Scala:如何按照元组的第二个元素对数组进行排序?

63

在Scala中,是否有一种方法可以使用任意比较函数对元组数组进行排序?特别是我需要根据它们的第二个元素对元组数组进行排序,但我想知道一般的技术来对元组数组进行排序。

谢谢!

7个回答

140
在Scala 2.8中,有一个名为sortBy的方法。以下是一个简单的示例用法:
scala> val arr = Array(("One",1),("Two",2),("Four",4),("Three",3))
arr: Array[(java.lang.String, Int)] = Array((One,1), (Two,2), (Four,4), (Three,3))

scala> arr.sortBy(_._2)
res0: Array[(java.lang.String, Int)] = Array((One,1), (Two,2), (Three,3), (Four,4))

scala>

11
2.8 就是在作弊。+1 - tstenner
好的。我得切换到2.8(目前使用的是2.7)。谢谢。 - pau.estalella
1
然而,这并不是原地排序。 - Daniel C. Sobral
@Daniel 是的,我刚写了一篇关于它的帖子:http://old.nabble.com/Is-it-possible-to-use-filter-or-sort-method-of-a-mutable-Seq-without-creating-new-Seq--td28222943.html - Eastsun

26

您可以使用以下代码:

scala> val v = Array(('a', 2), ('b', 1))
v: Array[(Char, Int)] = Array((a,2), (b,1))

scala> scala.util.Sorting.stableSort(v,
     | (e1: (Char, Int), e2: (Char, Int)) => e1._2 < e2._2)

scala> v
res11: Array[(Char, Int)] = Array((b,1), (a,2))

很遗憾,Scala 似乎无法推断传递给 stableSort 的数组类型。希望对你来说没问题。


稍微改进一下:stableSort(v, (_._2 < _._2) : ((Char,Int),(Char,Int)) => Boolean) — 将关注点分离开来,使得我们可以将逻辑和类型作为独立的步骤进行推理,特别是由于内联类型签名在这里只是一个麻烦。 - Erik Kaplun
需要注意的一件事是,如果您正在处理排序列中的任何类型(假设它具有长整型),则需要执行以下操作:scala.util.Sorting.stableSort(v,(e1:(String,Any),e2:(String,Any))=> e1._2.asInstanceOf [ Long] <e2._2.asInstanceOf [Long]) - Paul

9
如果要排序的对象是Array,使用原地排序算法可能很常见。然而,在符合Scala惯例的代码中,通常不鼓励/使用可变集合。如果是这种情况并且您有一个不可变的集合(或者不想原地修改Array),请使用sortWith函数:
scala> val a = Array(1, 3, 2, 5)
a: Array[Int] = Array(1, 3, 2, 5)

scala> a.sortWith(_ > _)
res6: Array[Int] = Array(5, 3, 2, 1)

scala> a
res7: Array[Int] = Array(1, 3, 2, 5)

对一个 Array 或者任何其他元组集合进行排序:

scala> val a = Array(('a', 1), ('b', 4), ('c', 5), ('d', 2))
a: Array[(Char, Int)] = Array((a,1), (b,4), (c,5), (d,2))

scala> a.sortWith(_._2 > _._2)
res4: Array[(Char, Int)] = Array((c,5), (b,4), (d,2), (a,1))

scala> a
res5: Array[(Char, Int)] = Array((a,1), (b,4), (c,5), (d,2))

1
我们在哪里可以找到关于“_._2”语法的信息?这被称为什么? - martin jakubik
1
也许这会有所帮助:https://dev59.com/bmsz5IYBdhLWcg3wR1zC - Erik Kaplun

3
在Scala 2.8(是的,又是它 :))中,您还可以这样做:
val v = Array(('a', 2), ('b', 1))
scala.util.Sorting.stableSort(v)(manifest[(Char, Int)], Ordering.by(_._2))

在对于一组键值对进行排序时,可以先按照第二个元素排序,再按照第一个元素排序:

在对于一组键值对进行排序时,可以先按照第二个元素排序,再按照第一个元素排序:

scala.util.Sorting.stableSort(v)(manifest[(Char, Int)], Ordering.by(_.swap))

2

2.7和非原地操作:

(Array((2,3), (4,2), (1,5)).toList.sort (_._2 < _._2)).toArray

1
你可能需要从scala.util.Sorting中使用def stableSort[K](a : Seq[K], f : (K, K) => Boolean) : Array[K]方法。
你的比较函数应该是这样的:_._2 < _._1

1
val l = List((2, 1), (3, 2), (0, 3))
l sort { case(a, b) => a > b }

问题是我有一个数组 :( - pau.estalella

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接