3

繰り返す可能性のあるさまざまなキーワードのリストがあります。個別のキーワードを含むリストを生成する必要がありますが、元のリストに出現する頻度で並べ替えます。

そのための慣用的な Scala はどのようになりますか? これは機能するが醜い実装です:

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")
4

8 に答える 8

8

短いバージョン:

keys.distinct.sortBy(keys count _.==).reverse

ただし、これは特に効率的ではありません。このgroupByバージョンはパフォーマンスが向上するはずですが、改善できる可能性があります。

keys.groupBy(identity).toSeq.sortBy(_._2.size).map(_._1)

reverseを宣言することで、最初のバージョンの を取り除くこともできますOrdering

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-24T06:48:15.873 に答える
2

コメントで修正できない実装に問題はありません。真剣に、それを少し分解して、各ステップを実行する理由と理由を説明してください。

おそらく「簡潔」ではないかもしれませんが、scala での簡潔なコードの目的は、コードをより読みやすくすることです。簡潔なコードが明確でない場合は、バックアップし、分割し (適切な名前のローカル変数を導入します)、コメントします。

于 2013-02-24T06:45:00.503 に答える
2

これが私の見解です。「醜い」かどうかはわかりません。

scala> keys.groupBy(p => p).values.toList.sortBy(_.size).reverse.map(_.head)
res39: List[String] = List(a, b, c)
于 2013-02-24T06:56:34.450 に答える
1

折りたたみバージョン:

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 }
于 2013-02-24T07:05:20.313 に答える
0

多分、

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)
于 2013-02-24T07:11:08.360 に答える
0

@Daniel の 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)
于 2013-02-24T09:19:01.557 に答える
0

どうですか:

keys.distinct.sorted

初心者は質問を注意深く読んでいませんでした。もう一度試してみましょう:

keys.foldLeft (Map[String,Int]()) { (counts, elem) => counts + (elem -> (counts.getOrElse(elem, 0) - 1))}
    .toList.sortBy(_._2).map(_._1)

必要に応じて、変更可能な Map を使用できます。負の頻度カウントがマップに格納されます。それが気になる場合は、それらを正にして、sortBy 引数を負にすることができます。

于 2013-02-24T06:48:54.450 に答える