我想按第3和第1个元素对元组数组进行排序,所以我使用了以下代码:
import scala.util.Sorting
val pairs = Array(("a", 5, 2), ("c", 3, 1), ("b", 1, 3))
// sort by the 3rd element, then 1st
Sorting.quickSort(pairs)(Ordering[(Int, String)].on(x => (x._3, x._1)))
我的问题是,在前面的例子中,我可以按第三个和第一个元素升序排序,或者两个元素都降序(使用反向)。但是如何按第三个元素升序和第一个元素降序排序。
请在答案中考虑以下情况:
Array[Array[People]]
在这种情况下,我不知道内部数组的确切大小(取决于我读入此数组的文件架构),我想按侧面的所有项目排序(一些升序和一些降序)。
编辑: 看起来,我很想念。
以下是我的完整案例: 我有以下课程:
sealed trait GValue extends Serializable with Ordered[GValue]{
def compare(o: GValue): Int = {
o match {
case GDouble(v) => this.asInstanceOf[GDouble].v compare v
case GString(v) => this.asInstanceOf[GString].v compare v
}
}
case class GDouble(v: Double) extends GValue
case class GString(v: String) extends GValue
我想做一个像这样的代码。
// (startInterval, StopInterval, ArrayOfColumns)
val intervals: Array[(Long,Long,Array[GValue])] =
Array((10,20,Array(GDouble(10.2), GString("alarm"), GString("error"),GDouble("100.234"))),
(30,2000,Array(GDouble(-10.2), GString("alarm"), GString("warn"),GDouble("0.234"))))
模式或内部数组将根据输入文件进行更改(在示例中,它是Double,String,String,Double但它可能是Double,Double或其他内容)。 我想找到一种方法来排序,覆盖内部数组的所有情况(关于类型和长度),升序和降序。
我目前所做的是将内部数组更改为Iterable,然后使用Ordering [Iterable [GValue]]进行排序或排序[Iterable [GValue]]。reverse。但我想按分开的方向排序(第一列升序,然后降序为第二列,然后升至第三列,依此类推)
答案 0 :(得分:3)
使用Régis Jean-Gilles' CompositeOrdering
from another question,我们可以撰写多个// Ordering to sort an Array[GValue] by column "col"
def orderByColumn(col: Int) = Ordering.by { ar: Array[GValue] => ar(col - 1) }
val `By Col3-Desc/Col1` =
CompositeOrdering(orderByColumn(3).reverse, orderByColumn(1))
val `By Col1/Col2/Col3` =
CompositeOrdering(orderByColumn(1), orderByColumn(2), orderByColumn(3))
。
Array[GValue]
现在我们可以对intervals
类型的数组进行排序,您可以使用sortBy
对intervals.sortBy(_._3)(`By Col3-Desc/Col1`)
进行排序:
intervals
如果您想使用Sorting.quickSort
对Ordering
数组进行排序,我们需要type Interval = (Long, Long, Array[GValue])
implicit object tupleByArray extends Ordering[Interval] {
def compare(a: Interval, b: Interval) = a._3 compare b._3
}
来表示元组:
intervals
现在,您可以使用Sorting.quickSort
implicit val arrOrd = `By Col3-Desc/Col1`
Sorting.quickSort(intervals)
// Array[(Long, Long, Array[GValue])] =
// Array(
// (30,2000,Array(GDouble(-10.2), GString(alarm), GString(warn), GDouble(0.234))),
// (10,20,Array(GDouble(10.2), GString(alarm), GString(error), GDouble(100.234)))
// )
进行排序
Array[People]
我在问题更新之前留下了答案:
在多个字段上排序时有great article by Eric Loots。
在您case class People(name: String, age: Int)
object PeopleOrdering {
// sort by name descending and age ascending
implicit object `By Name-Rev/Age` extends Ordering[People] {
def compare(a: People, b: People): Int = {
import scala.math.Ordered._
implicit val ord = Ordering.Tuple2[String, Int]
(b.name, a.age) compare (a.name, b.age)
}
}
}
val people = Array(People("Alice", 40), People("Bob", 50), People("Charlie", 20))
Sorting.quickSort(people)(PeopleOrdering.`By Name-Rev/Age`)
// > people
// Array[People] = Array(People(Bob,20), People(Bob,50), People(Alice,40))
val array = Array(people, Array(People("B", 1), People("C", 2)))
array.foreach(ps => Sorting.quickSort(ps)(PeopleOrdering.`By Name-Rev/Age`))
// > array
// Array[Array[People]] = Array(
// Array(People(Bob,20), People(Bob,50), People(Alice,40)),
// Array(People(C,2), People(B,1))
// )
的情况下,这可能如下所示:
accelerator
答案 1 :(得分:1)
对于您想要订购String
次序的示例,请在排序
implicit object ReverseStringOrdering extends Ordering[String] {
def compare(x: String, y: String) = -1 * x.compareTo(y)
}
因此,通常只需添加隐式Ordering
类型的对象,您希望使用重写的compare
方法对其进行降序排序。只有按不同类型排序时,此解决方案才有效。
如果您想按第一项升序和第二次降序排序,请在排序前添加:
implicit def AscFirstDescSecondTuple2[T1, T2](implicit ord1: Ordering[T1], ord2: Ordering[T2]): Ordering[(T1, T2)] =
new Ordering[(T1, T2)]{
def compare(x: (T1, T2), y: (T1, T2)): Int = {
val compare1 = ord1.compare(x._1, y._1)
if (compare1 != 0) return compare1
val compare2 = -1 * ord2.compare(x._2, y._2)
if (compare2 != 0) return compare2
0
}
}