【问题标题】:Scala - how to build an immutable map from a collection of Tuple2s?Scala - 如何从 Tuple2s 集合构建不可变映射?
【发布时间】:2017-08-23 23:13:41
【问题描述】:

在 Python 中,可以从可迭代的元组集合构造字典:

>>> listOfTuples = zip(range(10), [-x for x in range(10)])
>>> listOfTuples
[(0, 0), (1, -1), (2, -2), (3, -3), (4, -4), (5, -5), (6, -6), (7, -7), (8, -8), (9, -9)]
>>> theDict = dict(listOfTuples)
>>> theDict
{0: 0, 1: -1, 2: -2, 3: -3, 4: -4, 5: -5, 6: -6, 7: -7, 8: -8, 9: -9}
>>> 

是否有等效的 Scala 语法?我看到您可以使用 varargs 类型数量的 Tuple2s 来构建地图,例如

scala> val theMap = Map((0,0),(1,-1))
theMap: scala.collection.immutable.Map[Int,Int] = Map((0,0), (1,-1))

scala> theMap(0)
res4: Int = 0

scala> theMap(1)
res5: Int = -1

scala> val tuplePairs = List((0,0),(1,-1))
tuplePairs: List[(Int, Int)] = List((0,0), (1,-1))

scala> val mapFromIterable = Map(tuplePairs)
<console>:6: error: type mismatch;
 found   : List[(Int, Int)]
 required: (?, ?)
       val mapFromIterable = Map(tuplePairs)
                                 ^

我可以手动循环并分配每个值,但似乎必须有更好的方法。

scala> var theMap:scala.collection.mutable.Map[Int,Int] = scala.collection.mutable.Map()   
theMap: scala.collection.mutable.Map[Int,Int] = Map()

scala> tuplePairs.foreach(x => theMap(x._1) = x._2)                                     

scala> theMap
res13: scala.collection.mutable.Map[Int,Int] = Map((1,-1), (0,0))

【问题讨论】:

    标签: scala map


    【解决方案1】:

    使用 Scala 2.8.0 final,你可以这样做:

    
    scala> val tuplePairs = List((0,0),(1,-1))
    tuplePairs: List[(Int, Int)] = List((0,0), (1,-1))
    
    scala> tuplePairs.toMap
    res0: scala.collection.immutable.Map[Int,Int] = Map((0,0), (1,-1))
    

    如果您使用的是 Scala 2.7.7,您可以这样做,作为您使用的方法的替代方法:

    
    scala> val tuplePairs = List((0,0),(1,-1))
    tuplePairs: List[(Int, Int)] = List((0,0), (1,-1))
    
    scala> Map(tuplePairs: _*)
    res2: scala.collection.immutable.Map[Int,Int] = Map(0 -> 0, 1 -> -1)
    

    但是正如你所看到的,在 2.8.0 中,事情已经有了很大的改进。

    【讨论】:

    • 2.7 答案中的map 是不必要的。 Map() ++ tuplePairs 可以,Map(tuplePairs: _*) 也可以。
    【解决方案2】:

    虽然有一些答案可以提供很好的建议,但这是我认为最接近原始 python 代码的答案。

    // Scala 2.8
    val listOfTuples = (0 until 10) zip (for (x <- 0 until 10) yield -x)
    val theMap = Map(listOfTuples:_*)
    

    Scala 2.7 在 Ranges 上还没有 zip,因此您必须在第一个分配中将 Ranges 转换为 Lists:

    // Scala 2.7
    val listOfTuples = (0 until 10).toList zip (for (x <- 0 until 10) yield -x).toList
    val theMap = Map(listOfTuples:_*)
    

    【讨论】:

      【解决方案3】:

      有多种选择。首先(但不推荐,IMO),您可以使用 list:_*List 转换为可变参数或者,您可以使用 ++ 函数将值列表添加到地图中(这就是 Map.apply无论如何)

      scala> (Map[Int,Int]()) ++ List((1,2),(3,4))
      res4: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 3 -> 4)
      
      scala> Map(List((1,2),(3,4)):_*)
      res5: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 3 -> 4)
      

      【讨论】:

      • 为什么我的地图打印为 Map((1,-1), (0,0)) 而你的打印更漂亮的 Map(1 -> -1, 0 -> 0) ?有什么想法吗?
      • 实际上没有任何线索。还有人知道吗?嗯,这个终端还是2.7.7,这是为什么呢?
      【解决方案4】:

      我无法对已接受的答案发表评论(还没有足够的声誉),但为 Scala 2.7 提出的解决方案过于复杂:

      scala> Map() ++ (tuplePairs map (t => (t._1,t._2)))
      res2: scala.collection.immutable.Map[Int,Int] = Map(0 -> 0, 1 -> -1)
      

      “地图”没有做任何事情,它正在将 Tuple2 转换为 Tuple2。 这就够了:

      scala> Map() ++ tuplePairs
      res3: scala.collection.immutable.Map[Int,Int] = Map(0 -> 0, 1 -> -1)
      

      在我看来,使用 Map.empty 会更好:

      scala> Map.empty ++ tuplePairs
      res4: scala.collection.immutable.Map[Int,Int] = Map(0 -> 0, 1 -> -1)
      

      【讨论】:

      • 感谢您的信息。我永远不会找到 ++ 方法.. 你怎么搜索它?
      • 使用 ++ 不是我的主意,我只是删除了不必要的地图。不幸的是,2.7 scaladocs 似乎已从 scala-lang.org 中删除,但那里描述了 Map[A,B] 的 ++。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-09
      • 2011-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-10
      相关资源
      最近更新 更多