模拟 DB 的 sum

现有集合:

      var m2 = Map("name" -> "wang"
                   ,"sex" -> "1"
                   ,"dep" -> "it"
                   ,"salary" -> 2000)
      var list3 = List(m2
                      ,m2
                      ,Map("name" -> "yi"
                           ,"sex" -> "0"
                           ,"dep" -> "hr"
                           ,"salary" -> 2000))

从上面的代码中可以看出,我模拟了数据库中有 name、sex、dep、salary 这四个字段的表结构。

例如,我想求每个人的工资,我思路如下所示:

  • 提取有效的字段,即 name、salary,这里使用到了 map 函数,结果是类似 List[(Some(String),Some(Int)]
  • 依据 name 进行分组,这里使用了 groupby 函数,结果是 Map[Some(String),List[(Some(String),Some(Int)]]
  • 分组之后,得到一个 Map,而 Map 中的 value 值是一个 List,对 List 进行字段抽取,只保留 salary
  • 对 salary 进行 sum 计算

具体的代码如下所示:

      // func1 负责提取使用到的字段:name、salary
      var func1 = (x:Map[String,Any])=>{(x.get("name"),x.get("salary"))}
      //  func3 负责将 salary 进行汇总
      val func3 = (y:List[Int])=>{y.sum}
      val rs1 = list3.map(func1)
                     .groupBy(_._1)
                     .mapValues(_.map(_._2.get.asInstanceOf[Int]))
                     .mapValues(func3)

总结:

  • list + map 这种方式可以用来替代 web 开发中 JavaBean 的作用
  • 在这种类似链式编程的过程中会,scala 的编译器会对数据的类型向上转型,例如,字段抽取后,List[(Some(String),Some(Int)]
    如果,想要保留住字段的类型,可以使用 get.asInstanceOf[类型],来明确的指定数据类型
  • 以后就是在编写类似的代码的时候,一定参考编译器的类型提示来编写代码,因为他会帮我们找到正确的数据类型作为函数的参数

最后,再对应用场景做一下延伸,对有 n 指标的 m 个数值进行求和,代码如下:

      val rs10 =List(("wang","1","it",100,98)
                     ,("wang","0","it",200,98)
                     ,("wang","1","it",400,98)
                     ,("wang","1","it",500,98)
                    ).map((x:(String,String,String,Int,Int))=>{(x._1+x._2,x._4,x._5)})

      val func13 = (x:List[(String,Int,Int)])=>{x.map((a:((String,Int,Int))) =>{(a._2,a._3)})}
      println(rs10.groupBy(_._1)
                  .mapValues(func13)
                  .mapValues((x:List[(Int,Int)])=>{x.reduce((a:((Int,Int)),b:((Int,Int))) =>{(a._1+b._1,a._2+b._2)})}))

最后的最后, 其实可以对 n 指标的 m 个数值进行平均值、最大、最小、rownumber 的计算,这个就需要使用单独的编写递归函数了。

你可能感兴趣的:(scala)