[SCALA] 이 개지도를 병합과 같은 키의 값을 요약하는 가장 좋은 방법은?
SCALA이 개지도를 병합과 같은 키의 값을 요약하는 가장 좋은 방법은?
val map1 = Map(1 -> 9 , 2 -> 20)
val map2 = Map(1 -> 100, 3 -> 300)
내가 그들을 병합하고, 같은 키의 값을 합계를. 그래서 결과는 다음과 같습니다
Map(2->20, 1->109, 3->300)
지금은이 개 솔루션을 가지고 :
val list = map1.toList ++ map2.toList
val merged = list.groupBy ( _._1) .map { case (k,v) => k -> v.map(_._2).sum }
과
val merged = (map1 /: map2) { case (map, (k,v)) =>
map + ( k -> (v + map.getOrElse(k, 0)) )
}
그러나 나는 더 나은 솔루션이 있는지 알고 싶습니다.
해결법
-
==============================
1.Scalaz은 여기에 수행 할 작업을 캡처하고 짧은 / 깨끗한 솔루션을 틀림없이에 이르게 이는 반군의 개념이 있습니다 :
Scalaz은 여기에 수행 할 작업을 캡처하고 짧은 / 깨끗한 솔루션을 틀림없이에 이르게 이는 반군의 개념이 있습니다 :
scala> import scalaz._ import scalaz._ scala> import Scalaz._ import Scalaz._ scala> val map1 = Map(1 -> 9 , 2 -> 20) map1: scala.collection.immutable.Map[Int,Int] = Map(1 -> 9, 2 -> 20) scala> val map2 = Map(1 -> 100, 3 -> 300) map2: scala.collection.immutable.Map[Int,Int] = Map(1 -> 100, 3 -> 300) scala> map1 |+| map2 res2: scala.collection.immutable.Map[Int,Int] = Map(1 -> 109, 3 -> 300, 2 -> 20)
특히,지도에 대한 이항 연산자 [K는 V] 중복 된 값을 통해 V의 반군 연산자를 접는,지도의 키를 결합합니다. 각 중복 키 값의 합계를 얻을 수 있도록 인터넷 용 표준 반군은 또한 연산자를 사용합니다.
편집 : 조금 더 세부 사항, user482745의 요청에 따라.
수학적 반군 함께 그 세트로부터 두 개의 값을 얻어 조작자와, 단지 값의 세트이며, 그 세트에서 다른 값을 생성한다. 또한 이하의 정수, 예를 들면 반군, 그래서 - + 연산자 다른 INT 있도록 두개의 int 결합.
당신은 또한 당신이 어떻게 든 두 가지의 조합으로 새로운 하나를 생산하는 두 개의지도를 결합하여 몇 가지 동작을 가지고 올 수있는 너무 오래, "주어진 키 유형과 값 유형 모든지도"의 설정을 통해 반군을 정의 할 수 있습니다 입력.
모두지도에 표시 키가없는 경우,이 간단하다. 같은 키를 두 맵에 존재하는 경우, 우리는 그 키 맵에 두 값을 결합해야합니다. 흠, 우리는 단지 동일한 유형의 두 가지 요소를 결합하는 연산자를 설명하지? 이 Scalaz에지도를위한 반군 [K는, V] 존재 이유가되는 것은, V의 반군이 존재하는 경우에만 - V의 반군이 같은 키에 할당 된 두 개의 맵에서 값을 결합하는 데 사용됩니다.
지능 여기에 값 유형, 1 키의 "충돌"입니다 그래서 때문에 따라서, 값이 문자열 있었다면 100 + 9, A (즉 지능의 반군 운영자가하는 일의로) 두 매핑 된 값의 정수를 첨가하여 해결 (즉, 문자열에 대한 반군 운영자가하는 일이기 때문에, 다시) 충돌은 두 매핑 된 값의 문자열 연결 이어질 것입니다.
!. 문자열 연결은 교환 법칙이 성립하지 않기 때문에 (그리고 흥미롭게도, - 즉, "A"+ "B"= "B"+ "는"- 결과 반군 작업 중 하나 그래서 MAP1 아니다 | + | MAP2는 MAP2 다르다 | + | 문자열의 경우 MAP1가 아니라 지능의 경우).
-
==============================
2.나는이 알고있는 가장 짧은 대답은 표준 라이브러리가 사용
나는이 알고있는 가장 짧은 대답은 표준 라이브러리가 사용
map1 ++ map2.map{ case (k,v) => k -> (v + map1.getOrElse(k,0)) }
-
==============================
3.빠른 솔루션 :
빠른 솔루션 :
(map1.keySet ++ map2.keySet).map {i=> (i,map1.getOrElse(i,0) + map2.getOrElse(i,0))}.toMap
-
==============================
4.자, 이제 당신이 원하는 무언가가 스칼라 라이브러리 (최소 2.10에서)에서 - 기능을 통합. 하지만 그것은 단지의 HashMap에없는지도에 표시합니다. 그것은 다소 혼란입니다. 또한 서명은 복잡 - 내가 다른 키 쌍을 생성해야 할 것입니다 때 두 번 키를 필요로하고 줄 이유를 상상할 수 없다. 그러나 그럼에도 불구하고, 그것을 작동 이전의 "기본"솔루션보다 훨씬 청소기.
자, 이제 당신이 원하는 무언가가 스칼라 라이브러리 (최소 2.10에서)에서 - 기능을 통합. 하지만 그것은 단지의 HashMap에없는지도에 표시합니다. 그것은 다소 혼란입니다. 또한 서명은 복잡 - 내가 다른 키 쌍을 생성해야 할 것입니다 때 두 번 키를 필요로하고 줄 이유를 상상할 수 없다. 그러나 그럼에도 불구하고, 그것을 작동 이전의 "기본"솔루션보다 훨씬 청소기.
val map1 = collection.immutable.HashMap(1 -> 11 , 2 -> 12) val map2 = collection.immutable.HashMap(1 -> 11 , 2 -> 12) map1.merged(map2)({ case ((k,v1),(_,v2)) => (k,v1+v2) })
또한 scaladoc에 언급
-
==============================
5.이것은 그냥 일반 스칼라와 모노 이드로 구현 될 수있다. 다음은 샘플 구현입니다. 이 방법으로, 우리는 단지 2 만지도의 목록을 병합 할 수 있습니다.
이것은 그냥 일반 스칼라와 모노 이드로 구현 될 수있다. 다음은 샘플 구현입니다. 이 방법으로, 우리는 단지 2 만지도의 목록을 병합 할 수 있습니다.
// Monoid trait trait Monoid[M] { def zero: M def op(a: M, b: M): M }
이 개지도를 병합 모노 이드의 특성의지도를 기반으로 구현.
val mapMonoid = new Monoid[Map[Int, Int]] { override def zero: Map[Int, Int] = Map() override def op(a: Map[Int, Int], b: Map[Int, Int]): Map[Int, Int] = (a.keySet ++ b.keySet) map { k => (k, a.getOrElse(k, 0) + b.getOrElse(k, 0)) } toMap }
당신이 통합 될 필요가 맵의 목록이있는 경우 지금 (이 경우, 단지 2)는 다음과 같이 수행 할 수 있습니다.
val map1 = Map(1 -> 9 , 2 -> 20) val map2 = Map(1 -> 100, 3 -> 300) val maps = List(map1, map2) // The list can have more maps. val merged = maps.foldLeft(mapMonoid.zero)(mapMonoid.op)
-
==============================
6.
map1 ++ ( for ( (k,v) <- map2 ) yield ( k -> ( v + map1.getOrElse(k,0) ) ) )
-
==============================
7.나는 이것에 대해 블로그 포스트를 작성, 그것을 체크 아웃 :
나는 이것에 대해 블로그 포스트를 작성, 그것을 체크 아웃 :
http://www.nimrodstech.com/scala-map-merge/
기본적으로 scalaz 반 그룹을 사용하면 아주 쉽게이를 수 있습니다
같이 보일 것입니다 :
import scalaz.Scalaz._ map1 |+| map2
-
==============================
8.또한 고양이와 함께 그렇게 할 수 있습니다.
또한 고양이와 함께 그렇게 할 수 있습니다.
import cats.implicits._ val map1 = Map(1 -> 9 , 2 -> 20) val map2 = Map(1 -> 100, 3 -> 300) map1 combine map2 // Map(2 -> 20, 1 -> 109, 3 -> 300)
-
==============================
9.스칼라 2.13를 시작, 또 다른 솔루션 만 표준 라이브러리를 기반으로는 (그 이름에서 알 수 있듯이) mapValues 다음에 GROUPBY의 동등한와 감소 단계 groupMapReduce와 솔루션의 GROUPBY의 부품을 교체로 구성되어 있습니다 :
스칼라 2.13를 시작, 또 다른 솔루션 만 표준 라이브러리를 기반으로는 (그 이름에서 알 수 있듯이) mapValues 다음에 GROUPBY의 동등한와 감소 단계 groupMapReduce와 솔루션의 GROUPBY의 부품을 교체로 구성되어 있습니다 :
// val map1 = Map(1 -> 9, 2 -> 20) // val map2 = Map(1 -> 100, 3 -> 300) (map1.toSeq ++ map2).groupMapReduce(_._1)(_._2)(_+_) // Map[Int,Int] = Map(2 -> 20, 1 -> 109, 3 -> 300)
이:
-
==============================
10.여기에 내가 사용하는 결국 무엇을 :
여기에 내가 사용하는 결국 무엇을 :
(a.toSeq ++ b.toSeq).groupBy(_._1).mapValues(_.map(_._2).sum)
-
==============================
11.의 Andrzej 도일의 대답은 당신이를 사용할 수 있습니다 반군의 좋은 설명을 포함 | + | 오퍼레이터는 두 맵 가입 키와 일치하는 값을 합산한다.
의 Andrzej 도일의 대답은 당신이를 사용할 수 있습니다 반군의 좋은 설명을 포함 | + | 오퍼레이터는 두 맵 가입 키와 일치하는 값을 합산한다.
뭔가가 typeclass의 인스턴스로 정의 할 수있는 많은 방법이 있고, 영업과는 달리 당신은 특별히 키를 합계를하지 않을 수 있습니다. 또는, 당신은 교차로가 아닌 노동 조합에서 작동 수행 할 수 있습니다. Scalaz는이 목적을 위해지도하는 추가 기능을 추가합니다 :
https://oss.sonatype.org/service/local/repositories/snapshots/archive/org/scalaz/scalaz_2.11/7.3.0-SNAPSHOT/scalaz_2.11-7.3.0-SNAPSHOT-javadoc.jar/!/index.html#scalaz.std.MapFunctions
넌 할 수있어
import scalaz.Scalaz._ map1 |+| map2 // As per other answers map1.intersectWith(map2)(_ + _) // Do things other than sum the values
-
==============================
12.가장 빠르고 간단한 방법 :
가장 빠르고 간단한 방법 :
val m1 = Map(1 -> 1.0, 3 -> 3.0, 5 -> 5.2) val m2 = Map(0 -> 10.0, 3 -> 3.0) val merged = (m2 foldLeft m1) ( (acc, v) => acc + (v._1 -> (v._2 + acc.getOrElse(v._1, 0.0))) )
이 방법으로 요소의 각 즉시지도에 추가됩니다.
두 번째 ++ 방법입니다 :
map1 ++ map2.map { case (k,v) => k -> (v + map1.getOrElse(k,0)) }
첫 번째 방법과는 달리, 두 번째지도의 각 요소에 대한 두 번째 방법으로 새로운 목록이 생성됩니다 이전지도에 연결된.
CASE 표현식은 암시 적으로 적용 취소 방법을 사용하여 새 목록을 작성합니다.
-
==============================
13.이것은 내가 생각 해낸 것입니다 ...
이것은 내가 생각 해낸 것입니다 ...
def mergeMap(m1: Map[Char, Int], m2: Map[Char, Int]): Map[Char, Int] = { var map : Map[Char, Int] = Map[Char, Int]() ++ m1 for(p <- m2) { map = map + (p._1 -> (p._2 + map.getOrElse(p._1,0))) } map }
-
==============================
14.내가 일을 할 수있는 작은 기능을 가지고, 그것은 표준 lib 디렉토리에없는 자주 사용하는 기능을 내 작은 도서관에 있어요. 그것은 가변 및 불변의지도,뿐만 아니라 HashMaps을 모든 종류의 작업을해야
내가 일을 할 수있는 작은 기능을 가지고, 그것은 표준 lib 디렉토리에없는 자주 사용하는 기능을 내 작은 도서관에 있어요. 그것은 가변 및 불변의지도,뿐만 아니라 HashMaps을 모든 종류의 작업을해야
여기에 사용법은
scala> import com.daodecode.scalax.collection.extensions._ scala> val merged = Map("1" -> 1, "2" -> 2).mergedWith(Map("1" -> 1, "2" -> 2))(_ + _) merged: scala.collection.immutable.Map[String,Int] = Map(1 -> 2, 2 -> 4)
https://github.com/jozic/scalax-collection/blob/master/README.md#mergedwith
그리고 여기에 신체의
def mergedWith(another: Map[K, V])(f: (V, V) => V): Repr = if (another.isEmpty) mapLike.asInstanceOf[Repr] else { val mapBuilder = new mutable.MapBuilder[K, V, Repr](mapLike.asInstanceOf[Repr]) another.foreach { case (k, v) => mapLike.get(k) match { case Some(ev) => mapBuilder += k -> f(ev, v) case _ => mapBuilder += k -> v } } mapBuilder.result() }
https://github.com/jozic/scalax-collection/blob/master/src%2Fmain%2Fscala%2Fcom%2Fdaodecode%2Fscalax%2Fcollection%2Fextensions%2Fpackage.scala#L190
-
==============================
15.typeclass 패턴을 사용하여, 우리는 모든 숫자 유형을 병합 할 수 있습니다 :
typeclass 패턴을 사용하여, 우리는 모든 숫자 유형을 병합 할 수 있습니다 :
object MapSyntax { implicit class MapOps[A, B](a: Map[A, B]) { def plus(b: Map[A, B])(implicit num: Numeric[B]): Map[A, B] = { b ++ a.map { case (key, value) => key -> num.plus(value, b.getOrElse(key, num.zero)) } } } }
용법:
import MapSyntax.MapOps map1 plus map2
지도의 순서를 병합 :
maps.reduce(_ plus _)
from https://stackoverflow.com/questions/7076128/best-way-to-merge-two-maps-and-sum-the-values-of-same-key by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] 스칼라에서 더 높은 kinded 유형은 무엇입니까? (0) | 2019.10.29 |
---|---|
[SCALA] 스칼라 값으로 호출 대 이름으로 전화, 설명 필요 (0) | 2019.10.29 |
[SCALA] HashPartitioner는 어떻게 작동합니까? (0) | 2019.10.29 |
[SCALA] 유형의 차이를 적용 (0) | 2019.10.29 |
[SCALA] 어떻게 스파크에 dataframe에 RDD 개체를 변환하는 (0) | 2019.10.29 |