在Scala中,对复合键上的列表进行排序的正确方法是什么

时间:2014-03-11 18:43:21

标签: algorithm list scala sorting composite-key

我正在尝试从List中获取前N-1个元素。我在SO中经历了类似的帖子,例如herehere。我理解这些帖子中提出的解决方案背后的动机。但是,我认为我的问题有点不同。

我有一些元素的排序(降序)列表。让我们假设它已经以有效的方式排序,因为这不是重点。

是我所拥有的最顶端。但是,列表的其余部分有0个或更多重复项。每个重复项的 attr1 head 相同。我想提取这些重复项(如果有的话)。然后我想在第二个属性 attr2 上对此(顶部+重复)列表进行排序。换句话说,我想对复合​​键进行排序:首先是Key_1,然后是 - 对于相同的Key_1 - 按Key_2。

假设列表中的元素是一对。

case class PairOfAttrs(val int attr1,val int attr2)

/* .. more code here ... */

// Now, we obtain a sorted (descending) list of PairOfAttrs below
// Ordering is based on the value of attr1 (key_1)
val sortedPairsFirstAttr = .. // Seq(Pair1,Pair2,Pair3,Pair4....Pairn)

val top = sortedPairsFirstAttr.head

显然,top的attr1是列表中最高的。为了提取重复项,我做了:

val otherToppers = sortedPairsFirstAttr.tail.filter 
                   (e => e.attr1 == topper.attr1) // Expression(1)

这是关键点,恕我直言。我找不到重复项,直到隔离顶部并在比较期间使用其属性( attr1 )。

// Then, I create a new list of the toppers only

val semiToppers = if (!otherToppers.empty) {
                        List(topper) ++ otherToppers // Expression(2)
                  }

然后,我对结果列表进行排序。订购基于attr2(Key_2)的值

val finalToppers = semiToppers.sortWith(_._2 < _.2) // Expression(3)

所以,实际上,我已经使用复合键对原始列表进行了排序:在Key_1上降序排序,然后然后,在Key_2上按升序排序。

我知道 Experssion(1)可以针对长列表进行优化;我不需要浏览整个列表。我可以提前摆脱它。我也明白可以合并 Expression(2) Expression(3)。所以,我们可以把这两点放在一边。

我的问题是我的方法是否在功能上合适且可接受。如果没有,那么您认为更好,更惯用的方法是什么?

这是学习者的问题。所以,我全心全意地寻求你的意见/观察。

1 个答案:

答案 0 :(得分:2)

您的解决方案正常有效,因此我不会对此发表评论。您已经使用val和不可变数据结构,这是实现它的纯粹方式。 我会建议另一种方法,稍微更短,也可能会让你感兴趣:

由于您无论如何都要对列表进行预处理,我建议您首先对其进行排序lexicographically:首先降序 attr1 ,如果是平局,则升序 attR2位

scala> val originalList = Seq((1,0), (2,7), (3,1), (1,3), (2,5), (3,4), (3,2))
scala> val lst = originalList.sortBy(x => (-x._1, x._2))
lst: Seq[(Int, Int)] = List((3,1), (3,2), (3,4), (2,5), (2,7), (1,0), (1,3))

现在您只需从前面获取重复项,结果已经按 attr2 排序:

scala> lst.takeWhile(_._1 == lst.head._1)
res8: Seq[(Int, Int)] = List((3,1), (3,2), (3,4))