2014-02-28 8 views
2

몇 가지 고유 한 방법으로 튜플 목록을 그룹화해야합니다. 제가스칼라 : 튜플의 그룹화 목록

val l = List((1,2,3),(4,2,5),(2,3,3),(10,3,2)) 

그럼 I 그룹 번째 값 목록 및 그래서 결과가 있어야 제 값

세트로 매핑한다이 경우, 예를 들어

,

Map(2 -> Set(1,4), 3 -> Set(2,10)) 

지금까지 나는 이것을 생각해 냈다.

l groupBy { p => p._2 } mapValues { v => (v map { vv => vv._1 }).toSet } 

이 방법이 효과적이지만 훨씬 효율적인 방법이 있어야한다고 생각합니다.

+1

귀하의 솔루션은 괜찮다고 생각합니다. – serejja

답변

2

이것은 this question과 유사합니다. 기본적으로 @serejja가 말했듯이 접근법은 정확하고 가장 간결합니다. 당신은 마지막 map에 빌더 공장 인수로 collection.breakOut 사용하여 Set 유형 얻을 수있는 추가적인 반복을 절약 할 수있다 : 당신이 정말로 성능을 짜낼 필요가없는

l.groupBy(_._2).mapValues(_.map(_._1)(collection.breakOut): Set[Int]) 

당신은 아마이 넘어 가지 말았어야합니다. ,이 단계를 구축하는 동안 변경 가능한지도를 사용하여,이되어 무엇을

import collection.generic.CanBuildFrom 
import collection.mutable 

def toMultiMap[A, K, V, Values](xs: TraversableOnce[A]) 
    (key: A => K)(value: A => V) 
    (implicit cbfv: CanBuildFrom[Nothing, V, Values]): Map[K, Values] = { 
    val b = mutable.Map.empty[K, mutable.Builder[V, Values]] 
    xs.foreach { elem => 
    b.getOrElseUpdate(key(elem), cbfv()) += value(elem) 
    } 
    b.map { case (k, vb) => (k, vb.result()) } (collection.breakOut) 
} 

:


그렇지 않으면, 이것은 당신이 값을 수집 유형을 제어 할 수있는 같은 일반적인 toMultiMap 기능을 볼 수있는 방법입니다 변경 가능한 값 Builder (빌더는 CanBuildFrom 인스턴스에 의해 제공됨)에서 모아진 값이 있습니다. 모든 입력 요소에 대한 반복이 완료된 후, 변경 가능한 빌더 값 맵은 값 콜렉션 유형의 불변 맵으로 변환됩니다 (원하는 출력 콜렉션을 바로 얻으려면 다시 collection.breakOut 트릭 사용).

예는 :

val l     = List((1,2,3),(4,2,5),(2,3,3),(10,3,2)) 
val v     = toMultiMap(l)(_._2)(_._1) // uses Vector for values 
val s: Map[Int, Set[Int] = toMultiMap(l)(_._2)(_._1) // uses Set for values 

그래서 주석이 달린 결과 유형은 값 형식의 형식 유추를 지시합니다. 결과에 주석을 달지 않으면 Scala는 기본 콜렉션 유형으로 Vector을 선택합니다.