我想尝试类似于reduceByKey函数的foldLeft。 如果字母存在,则按值递增,否则将元组附加在HashMap中。
以下代码失败:
val output = input.toLowerCase.filter(Character.isLetter).map(x => (x,1)).foldLeft(HashMap.empty[Char,Int].withDefaultValue(0)){case (acc,(x,y))=> acc += x }
请提出建议。
答案 0 :(得分:3)
使用Scala 2.13,您可以使用新的groupMapReduce()
。
val output = "In-Pint".collect{case c if c.isLetter => c.toLower}
.groupMapReduce(identity)(_ => 1)(_+_)
//output: Map[Char,Int] = Map(p -> 1, t -> 1, i -> 2, n -> 2)
答案 1 :(得分:2)
分解代码段:
.toLowerCase.filter(Character.isLetter)
如@jwvh的答案所示,可以将其简化为.collect{case c if c.isLetter => c.toLower}
.map(x => (x, 1))
如果您打算使用foldLeft
,则不需要进行此转换。
.foldLeft(HashMap.empty[Char,Int].withDefaultValue(0)){case (acc, (x,y)) => acc += x}
这不会编译,因为+=
是不能应用于累加器的赋值。
要计算字符串中的不同字符,您的foldLeft
可以如下所示:
"abac".foldLeft(Map[Char, Int]()){
case (m, c) => m + (c -> (m.getOrElse(c, 0) + 1))
}
// res1: scala.collection.immutable.Map[Char,Int] = Map(a -> 2, b -> 1, c -> 1)
这个想法很简单:在foldLeft
的二进制运算符中,如果已经存在c -> m(c)+1
,则将其添加到现有Map c
中;其他c -> 0+1
。