[英]Scala MaxBy's Tuple
我有一個元組Seq
,它代表一個字數: (count, word)
例如:
我的目標是找到計數最高的單詞。 如果 2 個詞之間存在平局,我將選擇出現在詞典中最先出現的詞(又名字母順序)。
val wordCounts = Seq(
(10, "World"),
(5, "Something"),
(10, "Hello")
)
val commonWord = wordCounts.maxBy(_._1)
print(commonWord)
現在,此代碼段將返回(10, "World")
,因為這是第一個具有最大計數的元組。
我可以用.sortBy
然后.head
,但我想更有效。
我的問題是有什么方法可以改變maxBy
的排序,以達到預期的結果。
注意:我不喜歡使用.sortBy
,因為它是O(n*log(n))
而不是O(n)
。 我知道我可以使用.reduce
,但我想檢查是否可以調整.maxBy
?
Scala 版本 2.13
max
、 min
、 maxBy
和maxBy
等minBy
使用隱式Ordering
來定義兩個項目之間的比較。 Tuple2 有一個Ordering
的默認實現,但問題是它將對兩個元素應用相同的比較 - 而在您的情況下,您需要使用大於_._1 和小於_._2 。 但是,您可以通過反轉第一個元素來輕松解決此問題,因此可以解決此問題:
wordCounts.minBy(x => (-x._1, x._2))
您可以通過使用orElse()
將兩個Ordering
組合在一起來創建自己的Ordering
:
// can't use .orElseBy() because of the .reverse, so this is a bit verbose
val countThenAlphaOrdering =
Ordering.by[(Int, String), Int](_._1)
.orElse(Ordering.by[(Int, String), String](_._2).reverse)
或者你可以在這種情況下使用Ordering.Tuple2
:
val countThenAlphaOrdering = Ordering.Tuple2(Ordering[Int], Ordering[String].reverse)
然后
val wordCounts = Seq(
(10, "World"),
(5, "Something"),
(10, "Hello"),
)
wordCounts.max(countThenAlphaOrdering) // (10,Hello): (Int, String)
implicit val WordSorter: Ordering[(Int, String)] = new Ordering[(Int, String)]{
override def compare(
x: (Int, String),
y: (Int, String)
) = {
val iComp = implicitly[Ordering[Int]].compare(x._1, y._1)
if iComp == 0
-implicitly[Ordering[String]].compare(x._2, y._2)
else
iComp
}
}
val seq = Seq(
(10, "World"),
(5, "Something"),
(10, "Hello")
)
def main(args: Array[String]): Unit = println(seq.max)
您可以創建自己的Ordering[(Int, String)]
隱式,其比較方法如果不為零則返回元組中數字的比較,如果 int 比較為零,則返回字符串的比較。 如果您想稍后更改行為,請使用隱式定義的Ordering[Int]
和Ordering[String]
進行模塊化。 如果你不想使用這些,你可以用x._1.compareTo(y._1)
等implicitly[Orderint[Int]].compare(x._1, y._1)
替換implicitly[Orderint[Int]].compare(x._1, y._1)
等等。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.