字符串中唯一字符的计数

时间:2014-05-24 16:33:49

标签: scala

我需要编写一个函数,在给定输入List的情况下返回(Char, Int)String对。

我的解决方案产生了正确的结果,但我想知道是否有更好的方法:

def countChars(s: String): List[(Char, Int)] = {
    s.groupBy(c => c.toLower).flatMap(e => List((e._1, e._2.length))).toList
  }                                              

这会在工作表中生成如下结果:

countChars("Green Grass")
// res0: List[(Char, Int)] = List(('e', 2), ('s', 2), ('n', 1), ('a', 1), (' ', 1), ('g', 2), ('r', 2))

5 个答案:

答案 0 :(得分:8)

制作单例列表只是为了展平它是多余的。

"Green Grass".groupBy(c => c.toLower).map(e => (e._1, e._2.length)).toList

答案 1 :(得分:2)

如果您正在处理长字符串或字符串流,那么您的方法将不必要地使用太多内存 - 在您调用flatMap之前,您基本上存储了输入字符串中的所有字母。相反,您只需存储每个字母的出现次数:

import scala.collection.immutable.Map
"Green Grass".map(_.toLower).foldLeft(Map.empty[Char, Int]) { (m, char) =>
  val count = m.getOrElse(char, 0)
  m.updated(char, count+1)
}.toList

这会返回与您的解决方案相同的结果。

答案 2 :(得分:1)

有点美化的@dhg asnwer版本:

"Green Grass".groupBy(c => c.toLower).mapValues(group => group.length).toList

答案 3 :(得分:1)

Scala 2.13开始,我们可以使用groupMapReduce方法,该方法是groupBy / mapValues的单程替代方法:

"Green Grass".groupMapReduce(_.toLower)(_ => 1)(_ + _).toList
// List[(Char, Int)](('e', 2), ('s', 2), ('n', 1), ('a', 1), (' ', 1), ('g', 2), ('r', 2))

此:

  • group个小写字母(_.toLower)字符( MapReduce的组部分)

  • map将每个分组值出现的次数设为1(_ => 1)(映射组 Map Reduce)

  • reduce在一组值(_ + _)中的值相加(减少groupMap Reduce 的一部分)。

  • 使用Map[Char,Int]将结果List[(Char, Int)]转换为.toList

groupMapeduce阶段是one-pass version可以翻译的内容:

"Green Grass".groupBy(_.toLower).mapValues(_.map(_ => 1).reduce(_+_))

答案 4 :(得分:0)

你也可以试试这个

def countChars(s: String) =
  s.distinct.map(c => c -> s.count(_ == c))