字符串中唯一字符的计数

问题描述 投票:5回答:5

我需要编写一个函数,在给定输入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))
scala
5个回答
8
投票

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

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

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

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


1
投票

有点美化的@dhg回答版本:

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

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

这个:

  • groups字符的小写版本(_.toLower)(groupMapReduce的组部分)
  • maps每个分组值出现为1(_ => 1)(mapMapReduce的地图部分)
  • reduces通过求和它们(减少groupMapReduce的一部分)在一组值(_ + _)中的值。
  • 使用Map[Char,Int]将生成的List[(Char, Int)]转换为.toList

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

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

0
投票

你也可以试试这个

def countChars(s: String) =
  s.distinct.map(c => c -> s.count(_ == c))
© www.soinside.com 2019 - 2024. All rights reserved.