我正在尝试从List中获取前N-1个元素。我在SO中经历了类似的帖子,例如here和here。我理解这些帖子中提出的解决方案背后的动机。但是,我认为我的问题有点不同。
我有一些元素的排序(降序)列表。让我们假设它已经以有效的方式排序,因为这不是重点。
头是我所拥有的最顶端。但是,列表的其余部分有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)。所以,我们可以把这两点放在一边。
我的问题是我的方法是否在功能上合适且可接受。如果没有,那么您认为更好,更惯用的方法是什么?
这是学习者的问题。所以,我全心全意地寻求你的意见/观察。
答案 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))