Scala进阶之路

Stella981
• 阅读 413

Scala进阶之路-统计商家id的标签数以及TopN示例案例分析

作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

一.项目需求

将“temptags.txt”中的数据进行分析,统计出商家id的评论标签数量,由于博客园无法上传大文件的文本,因此我把该文本的内容放在博客园的另一个链接了(需要的戳我),如果网页打不开的话也就可以去百度云盘里下载副本,链接:https://pan.baidu.com/s/1daRiwOVe6ohn42fTv6ysJg 密码:h6er。

我之前使用Hadoop的MapReduce实现过,详情请参考:https://www.cnblogs.com/yinzhengjie/p/9332761.html,但是实在过于繁琐,在学习Scala的时候发现它实现起来更简单。

二.代码实现

  1 /*
  2 @author :yinzhengjie
  3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
  4 EMAIL:y1053419035@qq.com
  5 */
  6 
  7 package cn.org.yinzhengjie.scala
  8 
  9 /**
 10   * 单例模式
 11   */
 12 object TaggenDemo {
 13     //从json中抽取出所有评论,形成list返回
 14     def extractTags(json:String) :List[String] = {
 15         var list:List[String] = Nil
 16         /**
 17           * 注意这两个判断条件 :json != null && !json.equals("")
 18           *     1>.json != null:
 19           *         首先先说说null,这个null不管是在java还是Scala中它可以赋值给任意的引用数据类型。在调用toString方法时,都会抛
 20           *     空指针异常,即“java.lang.NullPointerException”。
 21           *     2>.!json.equals("")
 22           *         接下来我们说说空字符串(""),这个空字符串("")它的长度为多少呢?很显然空字符串的长度为“0”,那么问题来了,它和null
 23           *     有啥区别呢?打个简单的比方哈,在Java代码中,"String[] arr1 = null;"与"String[] arr2 = new String[0];"的区别你知道吗?
 24           *     估计看到这两句话很多小伙伴已经不需要我多做解释了吧,没错,变量arr1是没有被初始化的,而arr2是被初始化且其长度为0.
 25           */
 26         if(json != null && !json.equals("")){
 27             import com.alibaba.fastjson.JSON
 28             //构造json对象
 29             val obj = JSON.parseObject(json)
 30             //提取数组属性
 31             val arr = obj.getJSONArray("extInfoList")
 32             if(arr != null && arr.size() > 0){
 33                 //提取数组一个json对象
 34                 val first = arr.getJSONObject(0)
 35                 //标签集合
 36                 val tags = first.getJSONArray("values")
 37                 if(tags != null && tags.size() > 0){
 38                     for(i <- 0 until tags.size()){
 39                         list = tags.getString(i) :: list
 40                     }
 41                 }
 42             }
 43         }
 44         list
 45     }
 46     def main(args: Array[String]): Unit = {
 47         /**
 48           * 读取文件
 49           */
 50         import scala.io.Source
 51         val f = Source.fromFile("D:\\BigData\\JavaSE\\yinzhengjieData\\temptags.txt")
 52         val lines = f.getLines().toList
 53         /**
 54           * 切割每一行,提取busid ->tags
 55           */
 56         val var2 = lines.map(line=>{
 57             val arr = line.split("\t")
 58             val busid = arr(0)
 59             val json = arr(1)
 60             (busid , extractTags(json))
 61         })
 62         /**
 63           * 过滤集合的空评论
 64           */
 65         val var3 = var2.filter(!_._2.isEmpty)
 66         /**
 67           * 压扁var3 , 形成 : (busid,tag)
 68           */
 69         val var4 = var3.flatMap(t=>{
 70             var l:List[(String,String)] = Nil
 71             for(tag <- t._2){
 72                 l = (t._1 , tag) :: l
 73             }
 74             l
 75         })
 76         /**
 77           * 分组统计每个商家每条评论的数量,Map
 78           */
 79         var var5 = var4.groupBy(t=>t)
 80         /**
 81           * 统计每条评论个数,例如((75144086 , 环境优雅) , 22)
 82           */
 83         var var6 = var5.toList.map(t=>{
 84             (t._1._1, (t._1._2 ,t._2.size))
 85         })
 86         /**
 87           * 分组,将同一商家的所有评论聚在一起
 88           */
 89         var var7= var6.groupBy(t=>t._1)
 90 
 91         /**
 92           * mapValues方法只对value进行变换
 93           */
 94         var var8 = var7.mapValues(t=>{
 95             t.map(t=>t._2)
 96         })
 97         /**
 98           * 对每个商家的所有评论按照数量倒排序
 99           */
100         var var9= var8.mapValues(t=>{
101             t.sortBy(t=> -t._2 )
102         })
103         /**
104           * 按照上架第一个标签的评论数进行排序
105           */
106         var var10 = var9.toList.sortBy(t=>{
107             -t._2(0)._2
108         })
109         /**
110           * 取出前10个元素,有两种方式,即take或者slice.是不是发现Scala中实现topN要比Java中的MapReduce要简单的多?
111           */
112         val res = var10.take(10)        //当然我们也可以用切片的方式取出该元素:  val res = var10.slice(0,10)
113 
114         /**
115           * 打印我们得到的数据
116           */
117         for(e <- res){
118             println(e)
119         }
120     }
121 }
122 
123 
124 
125 /*
126 以上代码执行结果如下:
127 (75144086,List((8239,60), (服务热情,38), (8241,31), (效果赞,30), (环境优雅,22), (无办卡,22), (性价比高,21), (技师专业,21), (无推销,19), (价格实惠,18), (干净卫生,13), (体验好,12), (韩系风格,10), (美发师手艺好,3), (服务差,2), (美发效果好,1), (效果差,1)))
128 (77287793,List((干净卫生,29), (音响效果好,26), (环境优雅,26), (价格实惠,25), (交通便利,25), (性价比高,19), (服务热情,18), (高大上,16), (停车方便,13), (体验好,13), (服务一般,1), (音响效果差,1), (朋友聚会,1), (服务差,1)))
129 (74145782,List((服务热情,18), (味道赞,14), (干净卫生,13), (上菜快,13), (菜品不错,12), (分量足,11), (回头客,11), (环境优雅,11), (性价比高,6), (停车方便,5), (体验好,4), (不推荐,3), (服务差,2), (菜品差,2), (分量少,1), (6,1), (价格实惠,1), (体验差,1)))
130 (85648235,List((味道赞,17), (服务热情,15), (干净卫生,13), (上菜快,12), (回头客,11), (性价比高,10), (体验好,9), (价格实惠,8), (环境优雅,8), (分量足,7), (情侣约会,1)))
131 (83073343,List((干净卫生,17), (味道赞,16), (环境优雅,15), (菜品不错,11), (服务热情,11), (肉类好,9), (性价比高,8), (体验好,7), (分量足,7), (回头客,6), (价格实惠,4), (味道一般,1), (分量少,1), (5,1), (服务差,1), (上菜慢,1), (2,1)))
132 (73607905,List((菜品不错,16), (干净卫生,15), (回头客,15), (味道赞,14), (服务热情,14), (分量足,13), (性价比高,11), (肉类好,11), (环境优雅,7), (体验好,5), (上菜快,5), (体验差,2), (羊蝎子,1), (价格实惠,1)))
133 (73963176,List((味道赞,15), (价格实惠,12), (分量足,11), (菜品不错,10), (肉类好,7), (干净卫生,7), (服务热情,7), (环境优雅,6), (回头客,4), (性价比高,3), (价格高,1), (服务差,1), (味道一般,1)))
134 (78824187,List((价格实惠,13), (回头客,11), (分量足,10), (环境优雅,8), (性价比高,8), (干净卫生,7), (上菜快,6), (2,6), (服务热情,5), (主食赞,5), (味道赞,4), (1,1), (3,1), (服务差,1)))
135 (87994574,List((无推销,12), (价格实惠,8), (干净卫生,7), (服务热情,7), (效果赞,5), (无办卡,5), (环境优雅,4), (技师专业,3), (体验好,2), (没有异味,2), (韩系风格,1), (效果差,1)))
136 (76893145,List((服务热情,10), (环境优雅,7), (高大上,5), (味道赞,5), (咖啡厅,5), (回头客,4), (温馨浪漫,3), (服务一般,2), (体验好,2), (味道一般,2), (饮品赞,1), (性价比高,1)))
137  */
点赞
收藏
评论区
推荐文章
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
2年前
SQL语法基础之CREATE语句
SQL语法基础之CREATE语句作者:尹正杰版权声明:原创作品,谢绝转载!否则将追究法律责任。一.查看帮助信息1.使用“?”来查看MySQL命令的帮助信息mysql?CREATE  这里告诉我们CREATE命令需要和那些命令一起使用Manyhelpitems
Stella981 Stella981
2年前
Flume实战案例运维篇
Flume实战案例运维篇作者:尹正杰版权声明:原创作品,谢绝转载!否则将追究法律责任。一.Flume概述1.什么是Flume !(https://oscimg.oschina.net/oscnet/cfdbbae527024a725bbc602ba7b8e01d94f.png)
Wesley13 Wesley13
2年前
MongoDB入门
MongoDB入门Windows操作系统中Mongodb数据库的安装部署作者:尹正杰版权声明:原创作品,谢绝转载!否则将追究法律责任。一.数据库简介  博主推荐阅读:    https://www.cnblogs.com/yinzhengjie/p/11730035.html二.
Stella981 Stella981
2年前
Elastic Stack之Elasticsearch 5.6.12 集群部署实战
ElasticStack之Elasticsearch5.6.12集群部署实战作者:尹正杰版权声明:原创作品,谢绝转载!否则将追究法律责任。一.下载ElasticSearch1.查看ElasticSearch的发型版本(https://www.elastic.co/
Wesley13 Wesley13
2年前
HTML&CSS基础
HTML&CSS基础表单简介作者:尹正杰版权声明:原创作品,谢绝转载!否则将追究法律责任。一.HTML源代码<!DOCTYPEhtml<html<head<metacharset"UTF8"
Stella981 Stella981
2年前
Hadoop生态圈
Hadoop生态圈CentOs7.5单机部署ClickHouse作者:尹正杰版权声明:原创作品,谢绝转载!否则将追究法律责任。到了新的公司,认识了新的同事,生产环境也得你去适应新的集群环境,我新入职的公司的大数据开发同时并不看好hbase,而是对clickhouse青睐有加,听他们口头把ClickHouse吹的
Stella981 Stella981
2年前
GoLang基础数据类型
GoLang基础数据类型字符串处理大全作者:尹正杰版权声明:原创作品,谢绝转载!否则将追究法律责任。欢迎加入:  高级运维工程师之路        598432640任何一门语言都有它的好处,Golang的长处就是在于它的高并发能力,所以现在练习好Golang的用法,有利于你找一份好的工作哟~在学习任何一本语言
Stella981 Stella981
2年前
Docker自建仓库之Harbor高可用部署实战篇
Docker自建仓库之Harbor高可用部署实战篇作者:尹正杰版权声明:原创作品,谢绝转载!否则将追究法律责任。一.部署单机的Harbor1.部署单机版的Harbor  博主推荐阅读:    https://www.cnblogs.com/yinzhengjie/p/1223