首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何将Tuple2s of Tuple2s的Seq转换为映射的Tuple2

如何将Tuple2s of Tuple2s的Seq转换为映射的Tuple2
EN

Stack Overflow用户
提问于 2013-11-05 20:42:53
回答 3查看 96关注 0票数 2

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

代码语言:javascript
运行
复制
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来创建每个映射,如下所示:

代码语言:javascript
运行
复制
val map1 = (entries map { case(e1, _) => e1 }).toMap
val map2 = (entries map { case(_, e2) => e2 }).toMap

我猜想可能有一种方法可以在地图上一次传递就完成整个转换,这样我就可以这样做:

代码语言:javascript
运行
复制
val (map1, map2) = (entries accumulate { case(e1, e2) => // add e1 to map1, add e2 to map2 })

foldLeft可能会做到这一点,但也许还有更优雅的地方吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-11-05 21:21:57

使用标准库:

代码语言:javascript
运行
复制
val (map1, map2) = entries.unzip match {
  case (pairs1, pairs2) => (pairs1.toMap, pairs2.toMap)
}

对于斯卡拉兹,它是一个一条龙:

代码语言:javascript
运行
复制
val (map1, map2) = entries.unzip.bimap(_.toMap, _.toMap)

不过,这两种解决方案都会产生两个额外的中间序列。这可能不是你需要担心的事情,但如果你真的想要避免它,它实际上并不是那么不雅致:

代码语言:javascript
运行
复制
val (map1, map2) = entries.foldLeft(Map.empty[A, B], Map.empty[A, C]) {
  case ((map1, map2), (pair1, pair2)) => (map1 + pair1, map2 + pair2)
}

不需要斯卡拉斯。

票数 4
EN

Stack Overflow用户

发布于 2013-11-05 21:52:42

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

代码语言:javascript
运行
复制
val (s1, s2) = entries.unzip
val map1 = s1.toMap
val map2 = s2.toMap

然而,您仍然(1)遍历您的inputs以创建一个元组序列,然后(2)在unzip中再次遍历,然后(3)在s1.toMap中遍历,(4)再次在s2.toMap中遍历。

如果您关心的是最小的遍历,正如您的问题所暗示的,您需要手动构建结果。优雅,没有,但直截了当,您可以取消您的entries方法。

代码语言:javascript
运行
复制
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
EN

Stack Overflow用户

发布于 2013-11-05 21:46:37

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

代码语言:javascript
运行
复制
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])

    }

}
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19798570

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档