资料数据如下:
List(
("zhangsan", "河北", "鞋"),
("lisi", "河北", "衣服"),
("wangwu", "河北", "鞋"),
("zhangsan", "河南", "鞋"),
("lisi", "河南", "衣服"),
("wangwu", "河南", "鞋"),
("zhangsan", "河南", "鞋"),
("lisi", "河北", "衣服"),
("wangwu", "河北", "鞋"),
("zhangsan", "河北", "鞋"),
("lisi", "河北", "衣服"),
("wangwu", "河北", "帽子"),
("zhangsan", "河南", "鞋"),
("lisi", "河南", "衣服"),
("wangwu", "河南", "帽子"),
("zhangsan", "河南", "鞋"),
("lisi", "河北", "衣服"),
("wangwu", "河北", "帽子"),
("lisi", "河北", "衣服"),
("wangwu", "河北", "电脑"),
("zhangsan", "河南", "鞋"),
("lisi", "河南", "衣服"),
("wangwu", "河南", "电脑"),
("zhangsan", "河南", "电脑"),
("lisi", "河北", "衣服"),
("wangwu", "河北", "帽子")
)
方式一:先做wordcount ,对数据进行结构的转换
object Scala_wordcount01 { def main(args: Array[String]): Unit = { // TODO 需求 : 不同省份的商品点击排行 val dataList = List( ("zhangsan", "河北", "鞋"), ("lisi", "河北", "衣服"), ("wangwu", "河北", "鞋"), ("zhangsan", "河南", "鞋"), ("lisi", "河南", "衣服"), ("wangwu", "河南", "鞋"), ("zhangsan", "河南", "鞋"), ("lisi", "河北", "衣服"), ("wangwu", "河北", "鞋"), ("zhangsan", "河北", "鞋"), ("lisi", "河北", "衣服"), ("wangwu", "河北", "帽子"), ("zhangsan", "河南", "鞋"), ("lisi", "河南", "衣服"), ("wangwu", "河南", "帽子"), ("zhangsan", "河南", "鞋"), ("lisi", "河北", "衣服"), ("wangwu", "河北", "帽子"), ("lisi", "河北", "衣服"), ("wangwu", "河北", "电脑"), ("zhangsan", "河南", "鞋"), ("lisi", "河南", "衣服"), ("wangwu", "河南", "电脑"), ("zhangsan", "河南", "电脑"), ("lisi", "河北", "衣服"), ("wangwu", "河北", "帽子") ) // WordCount // (省份-商品, cnt) // TODO 2. 对数据进行结构的转换 // ("zhangsan", "河南", "电脑") => (河南-电脑) (word) val mapList = dataList.map( t => { t._2 + "-" + t._3 } ) // TODO 3, 将转换结构后的数据进行分组聚合 // (河南-电脑) => (河南-电脑, 100) // (河南-衣服) => (河南-衣服, 100) // (河北-衣服) => (河北-衣服, 100) val dataMap: Map[String, List[String]] = mapList.groupBy(data=>data) // dataMap.map( // t => { // val k = t._1 // val list = t._2 // (k, list.size) // } // ) // 如果对 K- V类型数据进行转换,但是K不变,只对V进行操作时,可以使用mapValues方法 val dataToCount = dataMap.mapValues(list=>list.size) //println(dataToCount) // TODO 4. 将聚合的结果进行结构转换 // (河南-电脑, 100) => ( 河南,(电脑,100) ) val prvToDataCountList: List[(String, (String, Int))] = dataToCount.toList.map( t => { val k = t._1 val v = t._2 val ks = k.split("-") (ks(0), (ks(1), v)) } ) //println(prvToDataCountList) // TODO 5. 将转换结构后的数据按照省份进行分组 // (河南, ( (电脑,100),(衣服,50) )) val groupMap: Map[String, List[(String, (String, Int))]] = prvToDataCountList.groupBy(_._1) // TODO 6. 将分组后的数据根据点击进行排序取前3名 val top3 = groupMap.mapValues( // List[(String, (String, Int))] list => { val newList = list.map(_._2) newList.sortBy(_._2)(Ordering.Int.reverse).take(3) } ) println(top3) } }
方式二:先对数据进行分组
object Scala_WordCount02 {
def main(args: Array[String]): Unit = {
//TODO 1.读取文件
val list = List(
("zhangsan", "河北", "鞋"),
("lisi", "河北", "衣服"),
("wangwu", "河北", "鞋"),
("zhangsan", "河南", "鞋"),
("lisi", "河南", "衣服"),
("wangwu", "河南", "鞋"),
("zhangsan", "河南", "鞋"),
("lisi", "河北", "衣服"),
("wangwu", "河北", "鞋"),
("zhangsan", "河北", "鞋"),
("lisi", "河北", "衣服"),
("wangwu", "河北", "帽子"),
("zhangsan", "河南", "鞋"),
("lisi", "河南", "衣服"),
("wangwu", "河南", "帽子"),
("zhangsan", "河南", "鞋"),
("lisi", "河北", "衣服"),
("wangwu", "河北", "帽子"),
("lisi", "河北", "衣服"),
("wangwu", "河北", "电脑"),
("zhangsan", "河南", "鞋"),
("lisi", "河南", "衣服"),
("wangwu", "河南", "电脑"),
("zhangsan", "河南", "电脑"),
("lisi", "河北", "衣服"),
("wangwu", "河北", "帽子")
)
val list1 = list.map((tuple1) => {
(tuple1._2, tuple1._3)
})
// println(list1) //去掉元组的第一个元素,名字
val list2 = list1.groupBy(_._1)
//println(list2) //按照省份分组
val list3 = list2.map((tuple) => {
(tuple._1, tuple._2.groupBy(_._2))
})
// println(list3)
val list4 = list3.map((tuple) => {
(tuple._1, tuple._2.map((kv) => {
(kv._1, kv._2.size)
}))
})
//println(list4)
val list5 = list4.toList
//println(list5)
val list6 = list5.map((a) => {
(a._1, a._2.toList.sortBy(-_._2))
})
println(list6)
//Map无序,要转换成list再进行排序,省份的Map和商品的Map,两次进行toList操作
}
}
运行结果
List((河南,List((鞋,6), (衣服,3), (电脑,2), (帽子,1))), (河北,List((衣服,6), (鞋,4), (帽子,3), (电脑,1))))