scala-在求和结束时获取总计
我有一个列表,我需要得到频率操作的总计数,作为结果末尾的附加元素scala-在求和结束时获取总计,scala,Scala,我有一个列表,我需要得到频率操作的总计数,作为结果末尾的附加元素 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[Strin
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)
我认为这会起作用:
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的第一条注释是使用operator
而不是为了简洁而更新的+
- @jwvh的第二个注释是删除
“total”->0,这显然是不必要的
- 重构两个键的递增值
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"))
如果您想玩它:
incrementValOfKeys
为调用acc的映射[String,Int]
增加keys
给定的每个键的值
其思想是在foldLeft
中以迭代方式完成调用:
incrementValOfKeys(映射当前状态、当前键、“总计”)
下面是一些incrementalofkeys
的示例,它对应于使用您在问题中给出的主foldLeft
计算a
的迭代步骤:
incrementValOfKeys(映射[String,Int]()。带默认值(0),“decimal”,“total”)
给出Map(“十进制”->1,“总计”->1)
incrementValOfKeys(Map[String,Int](“decimal”->1,“total”->1)。使用defaultvalue(0),“String”,“total”)
给出Map(“decimal”->1,“total”->2,“String”->1)
incrementvalof键(映射[String,Int](“十进制”->1,“总计”->2,“字符串”->1)。使用默认值(0),“字符串”,“总计”)
给出Map(“十进制”->1,“总计”->3,“字符串”->2)
- 等等
如果使用case(acc,x)=>acc+(x->(acc(x)+1)+(“total”->(acc(“total”)+1)),而不是调用它,则不必使用incrementValOfKeys
如果使用case(acc,x)=>acc+(“total”->(acc(“total”)+1))
而不必调用它。在构建映射时不需要累计总数,您只需使用输入的大小:
a.groupBy(identity).map{case (k, v) => k -> v.size} + ("total" -> a.size)
注意
2.13中的集合库有一个新的groupMapReduce
方法,该方法将使此过程更简单、更高效,如下所示:
a.groupMapReduce(identity)(_ => 1)(_+_) + ("total" -> a.size)
=>acc+(x->(acc(x)+1)+(“总计”->(acc(“总计”)+1))
@jwvh。。不,这也是一个错误。我用你第一次发布的代码测试了它<代码>映射(“总计”->0)
不需要。@jwvh。。是的,你是对的,它是有效的。。这很有效。。需要再次使用DefaultValue(0)给出什么?您的种子在开始时没有其他键,只有“total”
。因此,您希望更新在遇到新键时不会失败,例如“decimal”
。尝试不使用。使用默认值(0)
并将a
设置为List(“十进制”)
。我希望它会失败,而且是不言自明的。是的。。但是我们已经有了Map(“total”->0)
,它的默认权限是0?是的,但是它只适用于“total”
,不适用于其他键。这就是为什么一开始没有值的“decimal”
会抛出一个异常,因为在休闲地图上,如果之前没有插入键,你就不能毫无例外地调用acc(x)
。我编辑了以前的解决方案,删除了“total”->0
@stack0114106,并提供了一个链接来摆弄它。我希望这能让你更好地理解,如果情况还不是这样的话。