首页 文章

如何将Tuple2s的Seq of Tuple2s转换为Map的Tuple2

提问于
浏览
2

我有一系列数据要转换成一对 Map ;每个 Map 代表原始序列的单独转换 . 我可以生成元组,这些元组将在原始输入序列的单个传递中组成每个映射,如下所示:

val entries: Seq[((A, B), (A, C))] = input map { x =>
  val key = genKey(x)
  val tuple1 = key -> f(x)
  val tuple2 = key -> g(x)
}

我可以通过遍历生成的seq两次单独创建每个 Map ,如下所示:

val map1 = (entries map { case(e1, _) => e1 }).toMap
val map2 = (entries map { case(_, e2) => e2 }).toMap

我认为可能有一种方法可以在 Map 上的一次传递中完成整个转换,这样我就可以做到这样的事情:

val (map1, map2) = (entries accumulate { case(e1, e2) => // add e1 to map1, add e2 to map2 })

foldLeft可能会这样做,但也许有更优雅的东西?

3 回答

  • -1

    使用标准库:

    val (map1, map2) = entries.unzip match {
      case (pairs1, pairs2) => (pairs1.toMap, pairs2.toMap)
    }
    

    Scalaz是一个单行:

    val (map1, map2) = entries.unzip.bimap(_.toMap, _.toMap)
    

    但是,这两种解决方案都将创建两个额外的中间序列 . 这可能不是你需要担心的事情,但如果你真的想要避免它,折叠实际上并不是那么不优雅:

    val (map1, map2) = entries.foldLeft(Map.empty[A, B], Map.empty[A, C]) {
      case ((map1, map2), (pair1, pair2)) => (map1 + pair1, map2 + pair2)
    }
    

    不需要Scalaz .

  • 4

    如果你想使用上面的 entries 方法,那么显而易见的方法是:

    val (s1, s2) = entries.unzip
    val map1 = s1.toMap
    val map2 = s2.toMap
    

    但是你仍然(1)遍历你的 inputs 以创建一系列元组,然后(2)再次遍历 unzip ,然后(3)遍历 s1.toMap ,然后(4)再次在 s2.toMap 中遍历 .

    如果您的问题是最小的遍历,正如您的问题所暗示的那样,您需要手动构建结果 . 优雅,不,但直截了当,你可以取消你的 entries 方法 .

    val (map1, map2) = {
      val b1, b2 = Map.newBuilder[Int, String]
      input foreach { i =>
        val k = genKey(i)
        b1 += k -> f(i)
        b2 += k -> g(i)
      }
      (b1.result, b2.result)
    }
    
  • 2

    这将是我的方法(imho更容易掌握初学者):

    object TupleTest {
    
      def transform[A, B, C](entries: Seq[((A, B), (A, C))]): (Map[A, B], Map[A, C]) =
        {
    
          def acc[A, B, C](entries: Seq[((A, B), (A, C))], map1: Map[A, B], map2: Map[A, C]): (Map[A, B], Map[A, C]) =
            {
              entries match {
                case Nil => (map1, map2)
                case hd :: tl => acc(tl, map1.+(hd._1), map2.+(hd._2))
              }
    
            }
          acc(entries, Map.empty[A, B], Map.empty[A, C])
    
        }
    
    }
    

相关问题