[SCALA] 스칼라 :지도의 컬렉션을 병합하는 방법
SCALA스칼라 :지도의 컬렉션을 병합하는 방법
나는지도 [문자열, 더블]의 목록을 가지고 있고, 나는 하나의 맵 [문자열, 더블]에 그 내용을 병합하고 싶습니다. 어떻게 관용적 인 방법으로이 작업을 수행해야합니까? 나는이 배와 함께이 작업을 수행 할 수 있어야한다고 상상한다. 뭔가 같은 :
val newMap = Map[String, Double]() /: listOfMaps { (accumulator, m) => ... }
또한, 나는 일반적인 방법으로 키 충돌을 처리하고 싶습니다. 이미 존재한다는 것을, 나는 함수를 지정 할 수 있어야 내가지도에 키를 추가하는 경우 즉, 그 반환 (이 경우) 더블 및 해당 키에 대한 기존 값, 게다가 내가 추가 할 노력하고있어 값을 취 . 키가 아직지도에 존재하지 않는 경우, 그냥 그 값이 변경되지 않은 추가합니다.
내 특정 케이스에서 나는 하나의 맵 [문자열, 더블]지도 이미 키가 포함되어있는 경우, 다음 번 기존 맵 값에 추가됩니다하도록을 구축하고 싶습니다.
내 특정 코드에서 변경 가능한지도 함께 일하고 있어요,하지만 가능하면 내가 더 일반적인 솔루션에 관심이 있어요.
해결법
-
==============================
1.이건 어때:
이건 어때:
def mergeMap[A, B](ms: List[Map[A, B]])(f: (B, B) => B): Map[A, B] = (Map[A, B]() /: (for (m <- ms; kv <- m) yield kv)) { (a, kv) => a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv) } val ms = List(Map("hello" -> 1.1, "world" -> 2.2), Map("goodbye" -> 3.3, "hello" -> 4.4)) val mm = mergeMap(ms)((v1, v2) => v1 + v2) println(mm) // prints Map(hello -> 5.5, world -> 2.2, goodbye -> 3.3)
그리고 그것은 2.7.5과 2.8.0에서 모두 작동합니다.
-
==============================
2.글쎄, 당신은 할 수 있습니다 :
글쎄, 당신은 할 수 있습니다 :
mapList reduce (_ ++ _)
충돌에 대한 특별한 요구 사항을 제외하고.
당신은 특별한 요구 사항이 할 수 있기 때문에, 아마도 최고의는 다음과 같이 (2.8) 일 것이다 :
def combine(m1: Map, m2: Map): Map = { val k1 = Set(m1.keysIterator.toList: _*) val k2 = Set(m2.keysIterator.toList: _*) val intersection = k1 & k2 val r1 = for(key <- intersection) yield (key -> (m1(key) + m2(key))) val r2 = m1.filterKeys(!intersection.contains(_)) ++ m2.filterKeys(!intersection.contains(_)) r2 ++ r1 }
그런 다음 포주 내 도서관 패턴을 통해지도 클래스에이 방법을 추가하고, 대신 "++"의 원래 예제에서 사용할 수 있습니다 :
class CombiningMap(m1: Map[Symbol, Double]) { def combine(m2: Map[Symbol, Double]) = { val k1 = Set(m1.keysIterator.toList: _*) val k2 = Set(m2.keysIterator.toList: _*) val intersection = k1 & k2 val r1 = for(key <- intersection) yield (key -> (m1(key) + m2(key))) val r2 = m1.filterKeys(!intersection.contains(_)) ++ m2.filterKeys(!intersection.contains(_)) r2 ++ r1 } } // Then use this: implicit def toCombining(m: Map[Symbol, Double]) = new CombiningMap(m) // And finish with: mapList reduce (_ combine _)
keysIterator 2.7에 대한 키가되도록이가 2.8로 작성 동안 키, 필터는 필터와지도의 관점에서 작성해야, **되고, 등등, 너무 다른해서는 안됩니다 수 있습니다.
-
==============================
3.나는 아무도 아직이 솔루션을 마련하지 놀라게하고 있습니다 :
나는 아무도 아직이 솔루션을 마련하지 놀라게하고 있습니다 :
myListOfMaps.flatten.toMap
정확하게 당신이 필요합니까 :
예:
scala> List(Map('a -> 1), Map('b -> 2), Map('c -> 3), Map('a -> 4, 'b -> 5)).flatten.toMap res7: scala.collection.immutable.Map[Symbol,Int] = Map('a -> 4, 'b -> 5, 'c -> 3)
회전을 튜플의 단순 목록으로 맵의 목록을 평평하게, toMap 모든 중복 키가 제거와 맵에 튜플의 목록을 회전
-
==============================
4.(이 2.7.x에 대한 작업 또는 전혀 scalaz에있다처럼) 내가 뭔가를 누락하는 경우 그럴거야, 그래서 나는 빨리이 문제를 읽고 :
(이 2.7.x에 대한 작업 또는 전혀 scalaz에있다처럼) 내가 뭔가를 누락하는 경우 그럴거야, 그래서 나는 빨리이 문제를 읽고 :
import scalaz._ import Scalaz._ val ms = List(Map("hello" -> 1.1, "world" -> 2.2), Map("goodbye" -> 3.3, "hello" -> 4.4)) ms.reduceLeft(_ |+| _) // returns Map(goodbye -> 3.3, hello -> 5.5, world -> 2.2)
당신은 여기에 최대를 받고, 값을 축적하는 또 다른 방법을 두 번의 모노 이드의 정의를 변경하고 얻을 수 있습니다 :
implicit val dbsg: Semigroup[Double] = semigroup((a,b) => math.max(a,b)) ms.reduceLeft(_ |+| _) // returns Map(goodbye -> 3.3, hello -> 4.4, world -> 2.2)
-
==============================
5.재미있는,이 비트와 함께 주변에 noodling, 내가있어 (2.7.5에서) 다음 :
재미있는,이 비트와 함께 주변에 noodling, 내가있어 (2.7.5에서) 다음 :
일반지도 :
def mergeMaps[A,B](collisionFunc: (B,B) => B)(listOfMaps: Seq[scala.collection.Map[A,B]]): Map[A, B] = { listOfMaps.foldLeft(Map[A, B]()) { (m, s) => Map( s.projection.map { pair => if (m contains pair._1) (pair._1, collisionFunc(m(pair._1), pair._2)) else pair }.force.toList:_*) } }
그러나 프로젝션과 강제력과 toList와 이것 저것와 끔찍한이다 남자. 별도의 질문 : 배 내에서 그 처리하는 더 좋은 방법은 무엇입니까?
내 코드에서 처리하고, 덜 일반적인 솔루션으로 된 것입니다 변경할지도, 위해, 나는이있어 :
def mergeMaps[A,B](collisionFunc: (B,B) => B)(listOfMaps: List[mutable.Map[A,B]]): mutable.Map[A, B] = { listOfMaps.foldLeft(mutable.Map[A,B]()) { (m, s) => for (k <- s.keys) { if (m contains k) m(k) = collisionFunc(m(k), s(k)) else m(k) = s(k) } m } }
즉 조금 청소기를 보인다 있지만 변경할지도 만 작업 기록의 뜻으로. 대신 foldLeft의,하지만 난 종류의 오류를 얻고 있었다 : 흥미롭게도, / 사용 (필자는 질문을하기 전에) 내가 먼저 위의 시도. 나는 / 생각 : 및 foldLeft는 기본적으로 동등했지만, 컴파일러는 내가 명시 적 유형 (M, S)을 필요로 불평을 유지했다. 그 무엇이야?
-
==============================
6.나는 이것에 대해 블로그 포스트를 작성, 그것을 체크 아웃 :
나는 이것에 대해 블로그 포스트를 작성, 그것을 체크 아웃 :
http://www.nimrodstech.com/scala-map-merge/
기본적으로 scalaz 반 그룹을 사용하면 아주 쉽게이를 수 있습니다
같이 보일 것입니다 :
import scalaz.Scalaz._ listOfMaps reduce(_ |+| _)
-
==============================
7.스칼라 2.13부터 중복 키를 처리만을 표준 라이브러리에 기초하여 또 다른 용액 (이름 그대로) GROUPBY는 다음에 등가 인 새로운 groupMapReduce 연산자를 적용하기 전에 시퀀스 (편평한)로 맵을 병합하는 것으로 이루어진다 매핑 및 그룹화 값의 감소 단계 :
스칼라 2.13부터 중복 키를 처리만을 표준 라이브러리에 기초하여 또 다른 용액 (이름 그대로) GROUPBY는 다음에 등가 인 새로운 groupMapReduce 연산자를 적용하기 전에 시퀀스 (편평한)로 맵을 병합하는 것으로 이루어진다 매핑 및 그룹화 값의 감소 단계 :
List(Map("hello" -> 1.1, "world" -> 2.2), Map("goodbye" -> 3.3, "hello" -> 4.4)) .flatten .groupMapReduce(_._1)(_._2)(_ + _) // Map("world" -> 2.2, "goodbye" -> 3.3, "hello" -> 5.5)
이:
groupMapReduce 단계의 원 - 패스 버전 동등한 것으로 볼 수있다 :
list.groupBy(_._1).mapValues(_.map(_._2).reduce(_ + _))
-
==============================
8.그 사용 scalaz를 사용하는 것과 거의 같은 깨끗한 읽는 oneliner 도우미-FUNC :
그 사용 scalaz를 사용하는 것과 거의 같은 깨끗한 읽는 oneliner 도우미-FUNC :
def mergeMaps[K,V](m1: Map[K,V], m2: Map[K,V])(f: (V,V) => V): Map[K,V] = (m1 -- m2.keySet) ++ (m2 -- m1.keySet) ++ (for (k <- m1.keySet & m2.keySet) yield { k -> f(m1(k), m2(k)) }) val ms = List(Map("hello" -> 1.1, "world" -> 2.2), Map("goodbye" -> 3.3, "hello" -> 4.4)) ms.reduceLeft(mergeMaps(_,_)(_ + _)) // returns Map(goodbye -> 3.3, hello -> 5.5, world -> 2.2)
궁극의 가독성에 대한 암시 적 정의 유형에 포장 :
class MyMap[K,V](m1: Map[K,V]) { def merge(m2: Map[K,V])(f: (V,V) => V) = (m1 -- m2.keySet) ++ (m2 -- m1.keySet) ++ (for (k <- m1.keySet & m2.keySet) yield { k -> f(m1(k), m2(k)) }) } implicit def toMyMap[K,V](m: Map[K,V]) = new MyMap(m) val ms = List(Map("hello" -> 1.1, "world" -> 2.2), Map("goodbye" -> 3.3, "hello" -> 4.4)) ms reduceLeft { _.merge(_)(_ + _) }
from https://stackoverflow.com/questions/1262741/scala-how-to-merge-a-collection-of-maps by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] 어떻게 스칼라는 방법 정의에 여러 매개 변수를받을 수 있습니까? (0) | 2019.11.27 |
---|---|
[SCALA] 어떻게 그 값에 의한 scala.collection.Map [java.lang.String의, 지능] 정렬하려면? (0) | 2019.11.27 |
[SCALA] 자바의 ClassName.class의 스칼라 이에 상응하는 무엇입니까? (0) | 2019.11.27 |
[SCALA] 어떻게 플레이 2.0 환경에 따라 서로 다른 데이터베이스를 설정하는 방법? (0) | 2019.11.27 |
[SCALA] 스칼라 : 같음 / 해시 코드를위한 경우 클래스 필드를 무시? (0) | 2019.11.27 |