我需要编写一个函数,在给定输入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))
答案 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))