9

あなたが持っていると仮定します

val docs = List(List("one", "two"), List("two", "three"))

ここで、たとえば List("one", "two") は用語 "one" と "two" を含むドキュメントを表し、各用語のドキュメント頻度でマップを作成したい場合、つまりこの場合

Map("one" -> 1, "two" -> 2, "three" -> 1)

Scala でそれを行うにはどうすればよいでしょうか。(そして、はるかに大きなデータセットを想定すると、効率的な方法で。)

私の最初のJavaのような考えは、可変マップを使用することです:

val freqs = mutable.Map.empty[String,Int]
for (doc <- docs)
  for (term <- doc)
    freqs(term) = freqs.getOrElse(term, 0) + 1

これは十分に機能しますが、変更可能なマップに頼らずに、より「機能的な」方法でそれを行うにはどうすればよいでしょうか?

4

3 に答える 3

20

これを試して:

scala> docs.flatten.groupBy(identity).mapValues(_.size)
res0: Map[String,Int] = Map(one -> 1, two -> 2, three -> 1)

カウントに何度もアクセスする場合は、mapValues「怠惰」であり、アクセスのたびにサイズを再計算するため、避ける必要があります。このバージョンでは同じ結果が得られますが、再計算は必要ありません。

docs.flatten.groupBy(identity).map(x => (x._1, x._2.size))

identity関数は単に を意味しますx => x

于 2012-08-28T19:37:59.603 に答える
13
docs.flatten.foldLeft(new Map.WithDefault(Map[String,Int](),Function.const(0))){
  (m,x) => m + (x -> (1 + m(x)))}

なんという列車事故!

[編集]

あ、そのほうがいいです!

docs.flatten.foldLeft(Map[String,Int]() withDefaultValue 0){
  (m,x) => m + (x -> (1 + m(x)))}
于 2012-08-28T21:19:24.737 に答える
0

を開始し、リストのリストを ing したScala 2.13後、/のワンパス代替手段である which を使用できます。flattengroupMapReducegroupBymapValues

// val docs = List(List("one", "two"), List("two", "three"))
docs.flatten.groupMapReduce(identity)(_ => 1)(_ + _)
// Map[String,Int] = Map("one" -> 1, "three" -> 1, "two" -> 2)

これ:

  • flattensとしてのListsListList

  • groupリスト要素 ( identity) (グループMapReduce のグループ部分)

  • mapグループ化された値の出現ごとに 1 ( ) (グループMap Reduce_ => 1のマップ部分)

  • reduces 値のグループ内の値 ( _ + _) を合計する (groupMap Reduceの一部を減らす)。

于 2019-03-10T21:25:23.920 に答える