foldLeft:如果存在,则添加到地图中,否则更新值

时间:2019-07-30 07:41:08

标签: scala

我想尝试类似于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   }

请提出建议。

2 个答案:

答案 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