본문 바로가기
빅데이터/scala

[scala] 스칼라의 맵리듀스를 이용한 워드카운트 예제

by hs_seo 2019. 4. 9.

스칼라를 이용한 워드 카운트는 flatMap, map, groupBy, mapValues, reduce 함수를 이용해서 구할 수 있습니다.

 

입력으로 받는 문자열이 "Deer Bear River", "Car Car River", "Deer Car Bear" 일때 각 함수를 거치면서 어떻게 처리 되는지 확인해 보겠습니다.

 

#1번의 프로세스는 다음과 같습니다.

flatMap: split의 결과를 하나의 List로 합침

[ Deer, Bear, River, Car, Car, River, Deer, Car, Bear]

map: (문자, 1)로 반환

[ (Deer, 1), (Bear, 1), (River, 1), (Car, 1), (Car, 1), (River, 1), (Deer, 1), (Car, 1), (Bear, 1) ]

groupBy: 문자를 기준으로 그룹핑 처리(key: 문자, value: List(문자, 1)

{ Deer: [ (Deer, 1), (Deer, 1) ],

  Bear: [ (Bear, 1), (Bear, 1) ],

  River: [ (River, 1), (River, 1) ],

  Car: [ (Car, 1), (Car, 1), (Car, 1) ] }

mapVlues: key, value의 value만 처리

{ Deer: 2,

  Bear: 2,

  River: 2,

  Car: 3 }

 

#2번의 프로세스는 1번의 프로세스에서 groupBy 까지는 동일합니다. 거기서 1번 프로세스는 리스트의 배열의 길이로 처리하지만, 2번은 배열에서 튜플의 두번째 값인 1을 빼서 이 값으로 reduce 처리를 통해 값을 sum 해서 결과를 반환합니다.

map, reduce: value의 값만으로, (문자, 1)의 1만 반환하여 합침

{ Deer: [ (Deer, 1), (Deer, 1) ] -> sum([ 1, 1 ])

  Bear: [ (Bear, 1), (Bear, 1) ] -> sum([ 1, 1 ])

  River: [ (River, 1), (River, 1) ] -> sum([ 1, 1 ])

  Car: [ (Car, 1), (Car, 1), (Car, 1) ] -> sum([ 1, 1, 1 ])

 

package sdk.scala

object WordCount extends App {
  
  var words = List("Deer Bear River", "Car Car River", "Deer Car Bear")
  
  // #1
  val datas1 = words.flatMap(s => s.split(" "))
                    .map((_, 1))
                    .groupBy(_._1)
                    .mapValues(_.size)
  datas1.foreach(x => printf("word: %s, count: %d\n", x._1, x._2))
  
  // #2
  val datas2 = words.flatMap(s => s.split(" "))
                    .map((_, 1))
                    .groupBy(_._1)
                    .mapValues(x => x.map(x => x._2)
                                     .reduce(_ + _)
                              )
  datas2.foreach(x => printf("word: %s, count: %d\n", x._1, x._2))
}

 

 

반응형