scala打印字长直方图scala
scala printing word length histogram scala
我正在将一组行作为输入并跟踪字长的分布。额外的白色 space 包括输入中的换行符无关紧要。到达输入末尾后,输出是基于文本的字长分布直方图:
例如:"Hey How are you hey am good"
输出:
1 - 0, 2 - 1,
3 - 5,
4 - 1,
5 - 0
其中(第一个字符是单词的长度,第二个字符不是该长度的单词)。
我写了
val lines = scala.io.Source.stdin.getLines
val words = lines.flatMap(_.split("\W+"))
我想将相同长度的单词分组,然后将它们存储在迭代器或映射中
val list2 = words.groupby(e.length => e.length).mapValues(_.length)
没有给我想要的结果。
有什么建议吗?
嗯,Scala 集合提供了 groupBy 方法,在 Seq 的情况下它看起来像这样:
def groupBy[K](f: (A) ⇒ K): immutable.Map[K, Seq[A]]
这意味着它将一个函数应用于列表中的每个元素,并根据结果对它们进行分组。要按长度对单词进行分组,该函数应采用字符串 return 长度:
//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
参见 Map。
您已经基本掌握了,但您还需要 groupBy(e => e.length)
。匿名函数 (e => e.length
) 的左侧 (e
) 应该是一个变量名,它将用于集合中的每个项目(即每个单词)。所以e
是一个单词,我们按照单词的长度分组。
(此外,groupBy
的大写字母是 "B")。
val list2 = words.groupBy(e => e.length).mapValues(_.length)
如果你想要你描述的输出,你可以跟进:
val vectorOfLengths = (1 to list2.keys.max).map(length => list2.getOrElse(length, 0))
// Vector(0, 1, 5, 1)
println(vectorOfLengths.zipWithIndex.map{case (count, length) => f"${length+1} - $count" }.mkString(", "))
// 1 - 0, 2 - 1, 3 - 5, 4 - 1
或者,嘿,视觉上怎么样?
for ((count, length) <- vectorOfLengths.zipWithIndex)
println(f"${length+1}: ${"#" * count}")
// 1:
// 2: #
// 3: #####
// 4: #
只是为了好玩,Alice in Wonderland 的视觉直方图怎么样?
val aliceLines = io.Source.fromFile("/Users/dhg/texts/alice.txt").getLines.toVector
val aliceWords = aliceLines.flatMap(_.split("\W+"))
val aliceHist = aliceWords.groupBy(_.length).mapValues(_.length)
val aliceLengths = (1 to aliceHist.keys.max).map(aliceHist.getOrElse(_, 0))
for ((count, length) <- aliceLengths.zipWithIndex)
println(f"${length+1}%2s: ${"#" * (count/100)}")
// 1: ###################
// 2: ##################################################
// 3: ############################################################################
// 4: #############################################################
// 5: ###################################
// 6: ######################
// 7: ##################
// 8: ########
// 9: ######
// 10: ###
// 11: #
// 12:
// 13:
// 14:
// 15:
// 16:
我正在将一组行作为输入并跟踪字长的分布。额外的白色 space 包括输入中的换行符无关紧要。到达输入末尾后,输出是基于文本的字长分布直方图: 例如:"Hey How are you hey am good"
输出: 1 - 0, 2 - 1, 3 - 5, 4 - 1, 5 - 0
其中(第一个字符是单词的长度,第二个字符不是该长度的单词)。 我写了
val lines = scala.io.Source.stdin.getLines
val words = lines.flatMap(_.split("\W+"))
我想将相同长度的单词分组,然后将它们存储在迭代器或映射中
val list2 = words.groupby(e.length => e.length).mapValues(_.length)
没有给我想要的结果。 有什么建议吗?
嗯,Scala 集合提供了 groupBy 方法,在 Seq 的情况下它看起来像这样:
def groupBy[K](f: (A) ⇒ K): immutable.Map[K, Seq[A]]
这意味着它将一个函数应用于列表中的每个元素,并根据结果对它们进行分组。要按长度对单词进行分组,该函数应采用字符串 return 长度:
//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
参见 Map。
您已经基本掌握了,但您还需要 groupBy(e => e.length)
。匿名函数 (e => e.length
) 的左侧 (e
) 应该是一个变量名,它将用于集合中的每个项目(即每个单词)。所以e
是一个单词,我们按照单词的长度分组。
(此外,groupBy
的大写字母是 "B")。
val list2 = words.groupBy(e => e.length).mapValues(_.length)
如果你想要你描述的输出,你可以跟进:
val vectorOfLengths = (1 to list2.keys.max).map(length => list2.getOrElse(length, 0))
// Vector(0, 1, 5, 1)
println(vectorOfLengths.zipWithIndex.map{case (count, length) => f"${length+1} - $count" }.mkString(", "))
// 1 - 0, 2 - 1, 3 - 5, 4 - 1
或者,嘿,视觉上怎么样?
for ((count, length) <- vectorOfLengths.zipWithIndex)
println(f"${length+1}: ${"#" * count}")
// 1:
// 2: #
// 3: #####
// 4: #
只是为了好玩,Alice in Wonderland 的视觉直方图怎么样?
val aliceLines = io.Source.fromFile("/Users/dhg/texts/alice.txt").getLines.toVector
val aliceWords = aliceLines.flatMap(_.split("\W+"))
val aliceHist = aliceWords.groupBy(_.length).mapValues(_.length)
val aliceLengths = (1 to aliceHist.keys.max).map(aliceHist.getOrElse(_, 0))
for ((count, length) <- aliceLengths.zipWithIndex)
println(f"${length+1}%2s: ${"#" * (count/100)}")
// 1: ###################
// 2: ##################################################
// 3: ############################################################################
// 4: #############################################################
// 5: ###################################
// 6: ######################
// 7: ##################
// 8: ########
// 9: ######
// 10: ###
// 11: #
// 12:
// 13:
// 14:
// 15:
// 16: