복붙노트

[SCALA] 병합 키 매핑

SCALA

병합 키 매핑

나는이 개지도를 가지고 말 :

val a = Map(1 -> "one", 2 -> "two", 3 -> "three")
val b = Map(1 -> "un", 2 -> "deux", 3 -> "trois")

내가주는 서열로를 수집 할이 특별한 경우 (값을 수집하는 몇 가지 기능을 적용, 키를 기준으로이지도를 병합 할 :

val c = Map(1 -> Seq("one", "un"), 2 -> Seq("two", "deux"), 3 -> Seq("three", "trois"))

멋진,이 일의 관용적 방법이 있어야한다 것처럼 느낀다.

해결법

  1. ==============================

    1.scala.collection.immutable.IntMap는 (내가 믿는) 원하는 정확히 무엇 않는 intersectionWith 방법이 있습니다 :

    scala.collection.immutable.IntMap는 (내가 믿는) 원하는 정확히 무엇 않는 intersectionWith 방법이 있습니다 :

    import scala.collection.immutable.IntMap
    
    val a = IntMap(1 -> "one", 2 -> "two", 3 -> "three", 4 -> "four")
    val b = IntMap(1 -> "un", 2 -> "deux", 3 -> "trois")
    
    val merged = a.intersectionWith(b, (_, av, bv: String) => Seq(av, bv))
    

    이것은 당신을 IntMap 제공 (1 -> 목록 (한, 미), 2 -> 목록 (두 전차), 3 -> 목록 (세, 트루 아)). 참고 올바르게 단지에서 발생하는 키를 무시합니다.

    보조 노트로 : 나는 종종 자신이 등 unionWith, intersectionWith, 스칼라 하스켈의 Data.Map에서 기능을 원하는 것으로 나타났습니다. 나는 그들이 단지 대신 기본 collection.Map의 특성에 IntMap에 사용할 수 있어야한다는 어떤 원칙 이유가 있다고 생각하지 않습니다.

  2. ==============================

    2.

    val a = Map(1 -> "one", 2 -> "two", 3 -> "three")
    val b = Map(1 -> "un", 2 -> "deux", 3 -> "trois")
    
    val c = a.toList ++ b.toList
    val d = c.groupBy(_._1).map{case(k, v) => k -> v.map(_._2).toSeq}
    //res0: scala.collection.immutable.Map[Int,Seq[java.lang.String]] =
            //Map((2,List(two, deux)), (1,List(one, un), (3,List(three, trois)))
    
  3. ==============================

    3.Scalaz는 방법을 추가 | + | 모든 A 형에 대해 해당하는 반군 [A]를 사용할 수있다.

    Scalaz는 방법을 추가 | + | 모든 A 형에 대해 해당하는 반군 [A]를 사용할 수있다.

    각 값은 단일 요소의 순서였다 있도록지도 매핑 된 경우에, 당신은 아주 간단하게이를 사용할 수 있습니다 :

    scala> a.mapValues(Seq(_)) |+| b.mapValues(Seq(_))
    res3: scala.collection.immutable.Map[Int,Seq[java.lang.String]] = Map(1 -> List(one, un), 2 -> List(two, deux), 3 -> List(three, trois))
    
  4. ==============================

    4.나도 솔루션을 아주 행복하지 않았다 그래서 나는이 순간이와 함께 갔어요 그래서 (그래서 반군 정말 적절한 느낌, 그리고 무한대의 솔루션은 매우 복잡한 듯하지 않는 새로운 유형을 구축하려는). 나는 그것을 개선보고 드리겠습니다 :

    나도 솔루션을 아주 행복하지 않았다 그래서 나는이 순간이와 함께 갔어요 그래서 (그래서 반군 정말 적절한 느낌, 그리고 무한대의 솔루션은 매우 복잡한 듯하지 않는 새로운 유형을 구축하려는). 나는 그것을 개선보고 드리겠습니다 :

    def merge[A,B,C](a : Map[A,B], b : Map[A,B])(c : (B,B) => C) = {
      for (
        key <- (a.keySet ++ b.keySet);
        aval <- a.get(key); bval <- b.get(key)
      ) yield c(aval, bval)
    }
    merge(a,b){Seq(_,_)}
    

    키가 (다른 솔루션과 다릅니다) 중 하나를지도에없는 때 나는 아무것도 반환하지의 행동을 원하지만,이를 지정하는 방법이 좋을 것이다.

  5. ==============================

    5.여기에 다른 솔루션을 찾고 전에 나의 첫 번째 방법은 다음과 같습니다

    여기에 다른 솔루션을 찾고 전에 나의 첫 번째 방법은 다음과 같습니다

    for (x <- a) yield 
      x._1 -> Seq (a.get (x._1), b.get (x._1)).flatten
    

    단 A 또는 B에 존재하는 일을 피 요소에, 필터 편리합니다 :

    (for (x <- a) yield 
      x._1 -> Seq (a.get (x._1), b.get (x._1)).flatten).filter (_._2.size == 2)
    

    b.get (x._1)이 옵션을 반환하기 때문에 펼치기가 필요합니다. 패턴 화 작업을하려면 첫 번째 요소는 우리가 여기 x._2 사용할 수 없습니다, 너무 옵션을 수있다.

    순서의 경우, 너무 작동합니다 :

    scala> val b = Map (1 -> Seq(1, 11, 111), 2 -> Seq(2, 22), 3 -> Seq(33, 333), 5 -> Seq(55, 5, 5555))
    b: scala.collection.immutable.Map[Int,Seq[Int]] = Map(1 -> List(1, 11, 111), 2 -> List(2, 22), 3 -> List(33, 333), 5 -> List(55, 5, 5555))
    
    scala> val a = Map (1 -> Seq(1, 101), 2 -> Seq(2, 212, 222), 3 -> Seq (3, 3443), 4 -> (44, 4, 41214))
    a: scala.collection.immutable.Map[Int,ScalaObject with Equals] = Map(1 -> List(1, 101), 2 -> List(2, 212, 222), 3 -> List(3, 3443), 4 -> (44,4,41214))
    
    scala> (for (x <- a) yield x._1 -> Seq (a.get (x._1), b.get (x._1)).flatten).filter (_._2.size == 2) 
    res85: scala.collection.immutable.Map[Int,Seq[ScalaObject with Equals]] = Map(1 -> List(List(1, 101), List(1, 11, 111)), 2 -> List(List(2, 212, 222), List(2, 22)), 3 -> List(List(3, 3443), List(33, 333)))
    
  6. ==============================

    6.

    val fr = Map(1 -> "one", 2 -> "two", 3 -> "three")
    val en = Map(1 -> "un", 2 -> "deux", 3 -> "trois")
    
    def innerJoin[K, A, B](m1: Map[K, A], m2: Map[K, B]): Map[K, (A, B)] = {
      m1.flatMap{ case (k, a) => 
        m2.get(k).map(b => Map((k, (a, b)))).getOrElse(Map.empty[K, (A, B)])
      }
    }
    
    innerJoin(fr, en) // Map(1 -> ("one", "un"), 2 -> ("two", "deux"), 3 -> ("three", "trois")): Map[Int, (String, String)]
    
  7. ==============================

    7.스칼라 2.13를 시작, 당신은 (그 이름에서 알 수 있듯이) 값에 대한지도 다음에 GROUPBY의 등가 인에서는 groupMap을 사용할 수 있습니다 :

    스칼라 2.13를 시작, 당신은 (그 이름에서 알 수 있듯이) 값에 대한지도 다음에 GROUPBY의 등가 인에서는 groupMap을 사용할 수 있습니다 :

    // val map1 = Map(1 -> "one", 2 -> "two",  3 -> "three")
    // val map2 = Map(1 -> "un",  2 -> "deux", 3 -> "trois")
    (map1.toSeq ++ map2).groupMap(_._1)(_._2)
    // Map(1 -> List("one", "un"), 2 -> List("two", "deux"), 3 -> List("three", "trois"))
    

    이:

  8. from https://stackoverflow.com/questions/7755214/merge-maps-by-key by cc-by-sa and MIT license