在第三个元素交替的同时,基于第二个元素对元组列表进行排序

时间:2016-10-21 09:29:02

标签: algorithm scala sorting functional-programming tuples

给出一个元组列表:

val mylist = List(('orange', 0.9, 10), ('apple', 0.8, 10), ('mellon', 0.7, 10), 
                  ('car', 0.5, 2), ('truck', 0.5, 2),('tablet', 0.3, 3))

我想按照元组的第二个元素的降序对它们进行排序。但是,我想按类别选择它们,一次一个(第三个元素)。输出应该是以下列表:

('orange', 0.9, 10)
('car', 0.5, 2)
('tablet', 0.3, 3)
('apple', 0.8, 10) 
('truck', 0.5, 2)
('mellon', 0.7, 10) 

在Scala中执行此操作的功能方法是什么?

PS:注意结果必须反映第三个元素的排序,即10出现在2之前,2出现在3之前。

1 个答案:

答案 0 :(得分:3)

您可以通过向列表中的每个项目添加两个索引来执行此操作:

  • 所有现有类别中的项目类别位置(即类别10为0,1为2,2为3)
  • 项目在其类别中的索引按第二元组元素的降序值

添加完成后,您可以按顺序进行排序(使用优先类别的索引)

// traverse once to get a map of Category -> CategoryIndex
val categoryOrder: Map[Int, Int] = mylist.map(_._3).distinct.zipWithIndex.toMap

val result: List[(String, Double, Int)] = mylist
  .groupBy(_._3).mapValues(_.sortBy(-_._2).zipWithIndex) // add the index of each item within its category
  .toList.flatMap(_._2) // remove group keys and flatMap to get back to tuples
  .sortBy { case (t, indx) => (indx, categoryOrder(t._3)) } // order by index in category and category index
  .map(_._1) // remove indices

println(result)
// List((orange,0.9,10), (car,0.5,2), (tablet,0.3,3), (apple,0.8,10), (truck,0.5,2), (mellon,0.7,10))