我有一个列表,我需要获得频率运算的总数作为结果末尾的附加元素。
scala> val a = List("decimal","string","string","decimal","timestamp","decimal", "timestamp" )
a: List[String] = List(decimal, string, string, decimal, timestamp, decimal, timestamp)
scala> a.foldLeft(Map[String,Int]().withDefaultValue(0)){ case (acc,x) => acc+(x->(acc(x)+1)) }
res103: scala.collection.immutable.Map[String,Int] = Map(decimal -> 3, string -> 2, timestamp -> 2)
我需要的是
Map(decimal -> 3, string -> 2, timestamp -> 2, total -> 7)
我可以使用下面的代码
Map("total" -> a.size) ++ a.foldLeft(Map[String,Int]().withDefaultValue(0)){ case (acc,x) => acc+(x->(acc(x)+1)) }
但是如何使用a.foldLeft( Map("total" -> 0 ) )
实现。我正在尝试类似下面的操作,但出现错误。
scala> a.foldLeft( Map("total" -> 0 ) ){ case (acc,x) => acc+(x->(acc(x)+1)) }
java.util.NoSuchElementException: key not found: decimal
at scala.collection.MapLike$class.default(MapLike.scala:228)
at scala.collection.AbstractMap.default(Map.scala:59)
at scala.collection.MapLike$class.apply(MapLike.scala:141)
at scala.collection.AbstractMap.apply(Map.scala:59)
答案 0 :(得分:4)
我认为这可以解决问题:
val a = List("decimal","string","string","decimal","timestamp","decimal", "timestamp" )
a.foldLeft(Map("total" -> 0).withDefaultValue(0)) (
(acc,x) =>
acc.updated(x,acc(x) + 1)
.updated("total",acc("total") + 1)
)
编辑:我正在考虑:
+
而不是为了简洁而对@jwvh的第一条评论"total" -> 0
来@jwvh的第二条评论解决方案变为:
def incrementValOfKeys(acc: Map[String, Int], keys: String*) = keys.foldLeft(acc)(
(acc, key) => acc + (key -> (acc(key) + 1))
)
val a = List("decimal","string","string","decimal","timestamp","decimal", "timestamp" )
a.foldLeft(Map[String,Int]().withDefaultValue(0)) (incrementValOfKeys(_, _, "total"))
如果您想玩它:https://scalafiddle.io/sf/bAYBeNQ/0
incrementValOfKeys
以1
递增Map[String, Int]
的{{1}},每个键的值由acc
给出。
这个想法是在keys
中迭代地进行一次调用:
crementValOfKeys(映射当前状态,当前密钥,“总计”)
以下是foldLeft
的一些示例,它们与您在问题中给出的主要incrementValOfKeys
进行计算a
的迭代步骤相对应:
foldLeft
给出incrementValOfKeys(Map[String, Int]().withDefaultValue(0), "decimal", "total")
Map("decimal" -> 1, "total" -> 1)
给出incrementValOfKeys(Map[String, Int]("decimal" -> 1, "total" -> 1).withDefaultValue(0), "string", "total")
Map("decimal" -> 1, "total" -> 2, "string" -> 1)
给出incrementValOfKeys(Map[String, Int]("decimal" -> 1, "total" -> 2, "string" -> 1).withDefaultValue(0), "string", "total")
如果您使用Map("decimal" -> 1, "total" -> 3, "string" -> 2)
代替调用它,则不必使用incrementValOfKeys
。
答案 1 :(得分:3)
构建Map
时无需累计总数,只需使用输入的size
:
a.groupBy(identity).map{case (k, v) => k -> v.size} + ("total" -> a.size)
注意
2.13中的集合库具有一个新的groupMapReduce
方法,它将使此过程变得更加容易和有效,就像这样:
a.groupMapReduce(identity)(_ => 1)(_+_) + ("total" -> a.size)