groupBy 메소드는 Traversable 트레이트의 자식 클래스로, 그루핑할 때 사용한다.
예시로 빈도 별로 뽑고 싶다면 다음처럼 코드를 실행한다.
val names = List("Jackson", "Peter", "Jax", "Karl", "Jackson", "Jackson", "Jax")
println(names.groupBy(x => x.toString))
람다식 대신 _를 활용할 수 있다.
val names = List("Jackson", "Peter", "Jax", "Karl",
"Jackson", "Jackson", "Jax")
println(names.groupBy(_.toString))
결과는 다음과 같다.
Map(Karl -> List(Karl), Jax -> List(Jax, Jax), Jackson -> List(Jackson, Jackson, Jackson), Peter -> List(Peter))
엘리먼트의 length 별로 그룹핑할 수 있다. groupBy의 결과 타입은 Map이다.
val names = List("Jackson", "Peter", "Jax", "Karl",
"Jackson", "Jackson", "Jax")
println(names.groupBy(_.length))
결과는 다음과 같다.
Map(5 -> List(Peter), 4 -> List(Karl), 7 -> List(Jackson, Jackson, Jackson), 3 -> List(Jax, Jax))
같은 단어라면 보이지 않도록 distinct 메소드를 사용한다.
val unsorted = names.distinct.groupBy(_.length)val names = List("Jackson", "Peter", "Jax", "Karl",
"Jackson", "Jackson", "Jax")
println(unsorted)
결과는 다음처럼 깔끔해졌다.
Map(5 -> List(Peter), 4 -> List(Karl), 7 -> List(Jackson), 3 -> List(Jax))
하지만 length 별로 sorting이 되어 있지 않다. 이를 sort해보자.
이를 위해서는 바로 변환이 안된다. 먼저 Seq(ArrayBuffer)로 변환한 후, 다시 map으로 만든다.
Map을 Seq로 변환한후 sort한다. sort할 때 sortBy를 써서 1 번째 값(length)로 sort가 되게 한다.
sortBy 말고도 sortWith도 사용할 수 있다. sortWith는 자바와 compare 메소드와 비슷하다.
그리고, _*를 사용해서 Seq를 ListMap으로 변환한다.
val names = List("Jackson", "Peter", "Jax", "Karl",
"Jackson", "Jackson", "Jax")
val unsorted = names.distinct.groupBy(_.length)
println(unsorted)
//val sorted = unsorted.toSeq.sortBy(_._1)
val sorted = unsorted.toSeq.sortWith(_._1 < _._1)
println(sorted)
val map = ListMap(sorted:_*)
println(map)
결과는 다음과 같다.
Map(5 -> List(Peter), 4 -> List(Karl), 7 -> List(Jackson), 3 -> List(Jax))
ArrayBuffer((3,List(Jax)), (4,List(Karl)), (5,List(Peter)), (7,List(Jackson)))
Map(3 -> List(Jax), 4 -> List(Karl), 5 -> List(Peter), 7 -> List(Jackson))
마법의 키 sorted:_*가 궁금할 것이다.
sortBy, sortWith의 리턴 타입은 튜플을 엘리먼트로 갖는 Seq[(String, Int)]이다.
실행해보면, 아래와 같은 type mismatch 에러가 발생한다.
val map = ListMap(sorted)
Error:(26, 23) type mismatch;
found : Seq[(Int, List[String])]
required: (?, ?)
val map = ListMap(sorted)
따라서, ListMap의 생성자인 apply 메소드를 쫓아가면, GenMapFactory의 apply 메소드를 만나는데, 튜플의 가변 인자:(A, B)*를 받도록 되어 있다. 그래서 _*로 만들어 낸 것이다.
def apply[A, B](elems: (A, B)*): CC[A, B] = (newBuilder[A, B] ++= elems).result()
특이하긴 하지만, scala 공식 문서에도 나와 있는 내용이기도 하다.
http://docs.scala-lang.org/tutorials/FAQ/finding-symbols.html
f(xs: _*) // Sequence xs is passed as multiple parameters to
다시 groupBy로 넘어와서 case를 쓰는 예시를 사용한다.
val list = List(1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9)
val g = list.distinct.groupBy {
case num if (num % 2 == 0) => "짝수"
case _ => "홀수"
}
println(g)
결과는 다음과 같다.
Map(짝수 -> List(2, 4, 6, 8), 홀수 -> List(1, 3, 5, 7, 9))
val list = List(1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9)
val g = list.groupBy(x => x).mapValues(_.size)
println(g)
val list = List(1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9)
val g = ListMap(list.groupBy(x => x).mapValues(_.size).toSeq.sortBy(_._1):_*)
println(g)
결과는 다음과 같다.
Map(1 -> 2, 2 -> 1, 3 -> 1, 4 -> 1, 5 -> 1, 6 -> 1, 7 -> 1, 8 -> 1, 9 -> 3)
'scala' 카테고리의 다른 글
[scala] zip, unzip 예시 (0) | 2016.09.12 |
---|---|
[scala] Map의 transform, map, mapValues 예시, mapValues와 transform의 차이점 (0) | 2016.09.09 |
[scala] grouped와 sliding (0) | 2016.09.09 |
[scala] main 메소드 argument 처리 (0) | 2016.09.08 |
[scala] import 문 팁 - import static/import rename (0) | 2016.09.08 |