Scala中集合的方法求wordCount代码解析
wordcount的详细分析
def
main
(
args: Array
[
String
])
: Unit =
{
//
文本拆分成多行,把多行转换成一个集合
val
list:
List
[
String
]
= Source.
fromFile
(
"input/word.txt"
)
.getLines
()
.toList
println
(
list
)
//flatmap
是先
map
再
flatten
//
此时文本中的每一行就是一个元素,下面的下划线就是一行
//
得到的结果是一个一个的单词
val
wordList:
List
[
String
]
= list.flatMap
(
_.split
(
" "
))
//
对每个单词进行转换操作(单词,
1
)
val
word2OneList:
List
[(
String
, Int
)]
= wordList.map
((
_,
1
))
//
上面得到的结果是一个集合,集合中的内容是:(
hello,1
)
(word,1)(word,1)(hello,1)...
//
根据每个元素的
key
进行分组
//
表示的是按照对偶元素中的第一个元素
(
单词
)
分组。第一个下划线是每个元组,第二个
_1,
表示的是元组中的第一个元素
val
word2ListMap:
Map
[
String
,
List
[(
String
, Int
)]]
= word2OneList.groupBy
(
_._1
)
println
(
word2ListMap
)
//
上面是一个
map
集合,注意一下
map
的类型,表示的是相同的元组是放到了同一个
list
集合
//
上面的
Map
中的每个元素的格式是(单词名
->List((
单词名,
1)
(单词名,
1
)(单词名,
1
)
)
)
//Map中
元素的本质是元组,元组的第一个元素代表单词,第二个元素是一个
list
集合。最终操作的是每个元组
//map
当中
->
其实就是逗号的意思
val
word2CountMap:
Map
[
String
, Int
]
= word2ListMap.map
(
//map
后的小括号需要我们传递一个逻辑,使用匿名函数:()
=>{}
kv =>
{
//kv
表示的就是拿到的每个元素,元素的格式是: (单词名
->List((
单词名,
1)
(单词名,
1
)(单词名,
1
)
)
)
//
最后统计的格式是 (
hello,4
)
(word,3)
这种形式
(
kv._1, kv._2.size
)
//
格式就是(单词,对应的单词所在的集合的长度)
}
)
println
(
word2CountMap
)
/*
解析一下步骤 :文本
-->
多行
-->
(把每一行用空格拆分,把每行扁平化成一个一个单词)
-->(
单词名,
1)-->
按照单词的名称进行分组
-->
最后进行
map
(单词名,单词所在的集合的长度)
1
、
getlines.tolist:
把文本当中的每一行拿到。形成一个集合(集合当中的每个元素,就是文本当中的一行)
2
、
flatmap:flatmap
是先进行
map
操作,再进行
flatten
。先对每个元素(每一行)进行空格拆分,再对每一行进行扁平化操作(把一行,拆分出多个个体)
3
、扁平化之后,就是一个一个的单词了,这些单词在一个集合当中,只不过是单词之间无序,比较散。后面需要做的就是把相同的单词放到一起
4
、现在是为了把一个
List
集合中的元素变成 (单词,
1
)
5
、然后对集合中的元素进行分组,每个元素相同的
key
分到一组
6
、对
Map
中的每个元素进行
map
操作
注意:每次操作需要查看一下返回值类型,最好是每次都打印一下新的集合,可以帮助自己对集合中元素格式的理解
*/
}
遇到的问题.
1、自己想省略小括号,发现省略不了
2、每个操作都会返回一个新的集合
map是无序的,如果要排序需要转换成list
取前3:
有点难度的wordCount
问题:
求这种形式的wordcount:
val
dataList =
List
(
(
"Hello Scala"
,
4
)
,
(
"Hello Spark"
,
2
)
)
代码:
到这一步的时候被卡住,相同单词已经被分到同一个组当中,但是不知道如何去聚合相同单词的数量
很好的思路:因为后面的转换其实不需要了元组中的第一个元素了。只需要转换成 hello->List(4,2)
所以在map的时候,就只拿元组中的第二个元素,也就是
,第一个_2 是List 集合,第二个_2是元组中的第二个元素。
这个问题解决了后面也就流畅了
另外一种:类似九层妖塔,字符串和数字是可以相乘的
wordcount 难度版
object
ScalaWordCount6
{
def
main
(
args: Array
[
String
])
: Unit =
{
//("zhangsan", "
河北
", "
鞋
"),
val
tupleList =
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
tuplesNewList:
List
[(
String
,
String
)]
= tupleList.map
((
tuple
)
=>
{
(
tuple._2, tuple._3
)
})
println
(
tuplesNewList
)
/*
分析的一步步逻辑
("
河北
"
,
"
鞋子
")
,
("
河北
"
,
"
袜子
"),("
河北
"
,
"
鞋子
"),("
河北
"
,
"
衣服
")
"
河北
" ->List(
(
"
鞋子
"
,
4
),(
"
衣服
"
,
6
)
)
"
河南
"->List(
(
"
鞋子
"
,
4
),(
"
衣服
"
,
6
)
)
*/
println
(
tuplesNewList.groupBy
(
_._1
))
val
proviceToGoods:
Map
[
String
,
List
[(
String
,
String
)]]
= tuplesNewList.groupBy
(
_._1
)
val
goods:
Map
[
String
,
List
[
String
]]
= proviceToGoods.map
((
kv
)
=>
{
(
kv._1, kv._2.map
(
_._2
))
})
println
(
goods
)
val
goodsRudeuce:
Map
[
String
,
Map
[
String
,
List
[
String
]]]
= goods.map
((
kv
)
=>
{
(
kv._1, kv._2.groupBy
((
good
)
=>
{
good
}))
})
println
(
goodsRudeuce
)
val
proviceToGoodsCount:
Map
[
String
,
Map
[
String
, Int
]]
= goodsRudeuce.map
((
kv
)
=>
{
(
kv._1, kv._2.map
((
good
)
=>
{
(
good._1, good._2.size
)
}))
})
println
(
proviceToGoodsCount
)
val
list:
List
[(
String
,
Map
[
String
, Int
])]
= proviceToGoodsCount.toList
println
(
list
)
val
tuples:
List
[(
String
,
List
[(
String
, Int
)])]
= list.map
{
info =>
{
val
pro:
String
= info._1
val
goods:
List
[(
String
, Int
)]
= info._2.toList
val
res:
List
[(
String
, Int
)]
= goods.sortBy
(
_._2
)(
Ordering
.Int.reverse
)
(
pro, res
)
}
}
println
(
tuples
)
}
}
结果: