我有一個列表,包含可能重複的各種關鍵字。我需要生成具有不同關鍵字的列表,但按照它們出現在原始列表中的頻率排序。如何從列表中刪除重複項,然後按最頻繁排序
這將是怎樣的習慣斯卡拉?這是一個工作但醜陋的實現:
val keys = List("c","a","b","b","a","a")
keys.groupBy(p => p).toList.sortWith((a,b) => a._2.size > b._2.size).map(_._1)
// List("a","b","c")
我有一個列表,包含可能重複的各種關鍵字。我需要生成具有不同關鍵字的列表,但按照它們出現在原始列表中的頻率排序。如何從列表中刪除重複項,然後按最頻繁排序
這將是怎樣的習慣斯卡拉?這是一個工作但醜陋的實現:
val keys = List("c","a","b","b","a","a")
keys.groupBy(p => p).toList.sortWith((a,b) => a._2.size > b._2.size).map(_._1)
// List("a","b","c")
較短的版本:
keys.distinct.sortBy(keys count _.==).reverse
但是這並不是特別有效。該groupBy
版本應該有更好的表現,但它可以改進:
keys.groupBy(identity).toSeq.sortBy(_._2.size).map(_._1)
人們也可以在第一時間拿到的版本通過聲明Ordering
擺脫reverse
的:
val ord = Ordering by (keys count (_: String).==)
keys.distinct.sorted(ord.reverse)
注意,在這個reverse
版本只是產生一個新的Ordering
,它的工作原理與之相反。該版本還提出了一種方式來獲得更好的性能:
val freq = collection.mutable.Map.empty[String, Int] withDefaultValue 0
keys foreach (k => freq(k) += 1)
val ord = Ordering by freq
keys.distinct.sorted(ord.reverse)
很好找出關於身份:) – 2013-02-25 14:32:57
沒有錯,那個註釋無法修復的實現! 說真的,把它分解一點,並描述你爲什麼要採取每一步。
也許不是「簡潔」,但scala 簡潔代碼的目的是使代碼更具可讀性。當簡明代碼不清晰時,應該備份,分解(引入命名的局部變量)和註釋。
如何:
keys.distinct.sorted
新手沒仔細看這個問題。讓我再試一次:
keys.foldLeft (Map[String,Int]()) { (counts, elem) => counts + (elem -> (counts.getOrElse(elem, 0) - 1))}
.toList.sortBy(_._2).map(_._1)
如果您願意,可以使用可變映射。負頻率計數存儲在地圖中。如果這讓你感到困擾,你可以讓它們變得積極,並且否定這種討論。
這將按字母順序排序字符串。 – 2013-02-24 06:50:32
這裏是我拿的,不知道,如果它是不那麼 「醜」:
scala> keys.groupBy(p => p).values.toList.sortBy(_.size).reverse.map(_.head)
res39: List[String] = List(a, b, c)
折版本:
val keys = List("c","a","b","b","a","a")
val keysCounts =
(Map.empty[String, Int] /: keys) { case (counts, k) =>
counts updated (k, (counts getOrElse (k, 0)) + 1)
}
keysCounts.toList sortBy { case (_, count) => -count } map { case (w, _) => w }
也許,
val mapCount = keys.map(x => (x,keys.count(_ == x))).distinct
// mapCount : List[(java.lang.String, Int)] = List((c,1), (a,3), (b,2))
val sortedList = mapCount.sortWith(_._2 > _._2).map(_._1)
// sortedList : List[java.lang.String] = List(a, b, c)
距離變化不大@丹尼爾的第4版,可能會有更好的表現:
scala> def sortByFreq[T](xs: List[T]): List[T] = {
| val freq = collection.mutable.Map.empty[T, Int] withDefaultValue 0
| xs foreach (k => freq(k) -= 1)
| xs.distinct sortBy freq
| }
sortByFreq: [T](xs: List[T])List[T]
scala> sortByFreq(keys)
res2: List[String] = List(a, b, c)
我的首選版本是:
最經典/表現?
keys.groupBy(identity).toList.map{ case (k,v) => (-v.size,k) }.sorted.map(_._2)
最短也可能是最有效的?
keys.groupBy(identity).toList.sortBy(-_._2.size).map(_._1)
直截了當
keys.groupBy(identity).values.toList.sortBy(-_.size).map(_.head)
爲什麼醜嗎? – Rogach 2013-02-24 06:43:58
好吧,這感覺就像是有更合適的功能,我錯過了,如摺疊或聚合,將用於使其更清晰。 – 2013-02-24 06:46:58
如果有一個groupBy的變體,你可以傳遞一個函數來說明如何將下一個值合併/摺疊到分組鍵中是否有用?有任何數量的問題/答案在這裏它是groupBy +映射在它的價值陷入所需的結果... – 2013-02-24 11:30:21