2

一連の行を入力として取り込み、語長の分布を追跡しています。入力の改行を含む余分な空白は問題ではありません。入力の終わりに達した後、出力は単語の長さの分布のテキストベースのヒストグラムです: 例: "Hey How are you hey am good"

出力:1 - 0、2 - 1、3 - 5、4 - 1、5 - 0

ここで (最初の文字は単語の長さで、2 番目の文字はその長さの単語の数です)。私は書いた

val lines = scala.io.Source.stdin.getLines
val words = lines.flatMap(_.split("\\W+"))

同じ長さの単語をグループ化し、イテレータまたはマップに格納したい

val list2 = words.groupby(e.length => e.length).mapValues(_.length) 

望ましい結果が得られません。助言がありますか?

4

2 に答える 2

1

さて、Scala コレクションには groupBy メソッドが用意されていますが、 Seqの場合は次のようになります。

def groupBy[K](f: (A) ⇒ K): immutable.Map[K, Seq[A]]

つまり、リスト内のすべての要素に関数を適用し、結果に基づいてそれらをグループ化します。単語を長さでグループ化するには、関数は文字列を受け取り、その長さを返す必要があります。

//words: Seq[String] = Seq(a, b, c, dd, eee, fff)
val byLength = words.groupBy{(w:String) => w.length}//Map(2 -> Seq(dd), 
                                                    //    1 -> Seq(a, b, c), 
                                                    //    3 -> Seq(eee, fff))

または、パラメーターの型宣言を省略して、少し短くすることもできます。コンパイラーはあなたを理解します。

val byLength = words.groupBy(w => w.length)

または、アンダースコアプレースホルダーを使用して無名関数を定義することもできます:

val byLength = words.groupBy(_.length) //same thing

指定した長さの単語を取得できるようになりました。

val singleCharacterWords = byLength(1) //Seq(a, b, c)

または、マップにある程度の長さが含まれているかどうかを確認します

byLength.contains(1) //true
byLength.contains(5) //false

またはすべてのキーを反復処理します。

byLength.foreach{
  case (length:Int, wordsGroup:Seq[String]) => 
    println(s"Words with length $length : ${wordsGroup.mkString(" ")}")
}
//Words with length 2 : dd
//Words with length 1 : b c
//Words with length 3 : eee fff

そのための地図を参照してください。

于 2015-01-26T16:22:20.733 に答える