【问题标题】:How do I convert a Map[Int, Any] to a SortedMap in Scala? Or a TreeMap?如何在 Scala 中将 Map[Int, Any] 转换为 SortedMap?还是树状图?
【发布时间】:2011-03-05 16:26:50
【问题描述】:

我想将Map[Int, Any] 转换为SortedMapTreeMap。有什么简单的方法吗?

【问题讨论】:

    标签: scala


    【解决方案1】:

    如 sblundy 所述,使用 :_* 的替代方法是将现有映射附加到空的 SortedMap

    import scala.collection.immutable.SortedMap
    val m = Map(1 -> ("one":Any))
    val sorted = SortedMap[Int, Any]() ++ m
    

    【讨论】:

    • 在性能方面与其他选项相比如何?
    • 我会把它写成val sorted = SortedMap.empty[Int,Any] ++ m,因为它看起来像是在构造一个浪费的空映射,尽管希望编译器足够聪明,不会这样做。
    【解决方案2】:

    假设您使用的是不可变地图

    val m = Map(1 -> "one")
    val t = scala.collection.immutable.TreeMap(m.toArray:_*)
    

    TreeMap 伴随对象的 apply 方法采用重复的映射条目参数(它们是适当参数类型的 Tuple2[_, _] 的实例)。 toArray 产生一个Array[Tuple2[Int, String]](在这种特殊情况下)。 : _* 告诉编译器数组的内容将被视为重复参数。

    【讨论】:

    • 这是一个正确的答案。但它显示了 scala 集合丑陋的一面:太尴尬了。
    • 这是否会将 m 的全部内容作为方法参数推入堆栈?还是 Scala/Java 比这更聪明?
    • 这个解决方案效率低下,因为它首先将Map的整个副本复制到一个数组中,然后将该数组复制到一个TreeMap.Builder中。
    【解决方案3】:

    这是在各种 Scala 集合之间进行转换的一般方法。

    import collection.generic.CanBuildFrom
    import collection.immutable.TreeMap
    
    object test {
      class TraversableW[A](t: Traversable[A]) {
        def as[CC[X] <: Traversable[X]](implicit cbf: CanBuildFrom[Nothing, A, CC[A]]): CC[A] = t.map(identity)(collection.breakOut)
        def to[Result](implicit cbf: CanBuildFrom[Nothing, A, Result]): Result = t.map(identity)(collection.breakOut)
      }
    
      implicit def ToTraverseableW[A](t: Traversable[A]): TraversableW[A] = new TraversableW[A](t)
    
      List(1, 2, 3).as[Vector]
      List(1, 2, 3).to[Vector[Int]]
      List((1, 1), (2, 4), (3, 4)).to[Map[Int, Int]]
      List((1, 1), (2, 4), (3, 4)).to[TreeMap[Int, Int]]
      val tm: TreeMap[Int, Int] = List((1, 1), (2, 4), (3, 4)).to
      ("foo": Seq[Char]).as[Vector]
    }
    
    test
    

    另见描述collection.breakOut的这个问题:Scala 2.8 breakOut

    挑战

    是否可以调整隐式以使其有效?还是只有将as 添加到Traversable 才能实现?

    "foo".as[Vector]
    

    【讨论】:

    • 您可以使隐式接收绑定的视图而不是 Traversable,但我想不出从中检索“A”的方法。毕竟,String 没有“A”。
    • 我遇到了同样的问题。 A 应该是 Char。将 (Int, Int) 作为 Map 的元素类型检索的类似问题。
    • @retronym - 非常感谢您在我简单的“scala newbie”问题上的帖子。使用您在 collection.breakout 上发布的链接向我发送了一次良好的潜水。
    • IttayD:我怀疑这解决了一个稍微不同的问题,但需要更仔细地研究它。谢谢!
    • 假设比赛仍然开放,我会这样做:ideone.com/pVZVW
    【解决方案4】:

    Scala 2.13开始,通过工厂建设者申请.to(factory)

    Map(1 -> "a", 2 -> "b").to(collection.immutable.SortedMap)
    // collection.immutable.SortedMap[Int,String] = TreeMap(1 -> "a", 2 -> "b")
    
    Map(1 -> "a", 2 -> "b").to(collection.immutable.TreeMap)
    // collection.immutable.TreeMap[Int,String] = TreeMap(1 -> "a", 2 -> "b")
    

    【讨论】:

      【解决方案5】:

      这是一种使用 Scala 隐式类的方法:

      implicit class ToSortedMap[A,B](tuples: TraversableOnce[(A, B)])
                                     (implicit ordering: Ordering[A]) {
        def toSortedMap =
          SortedMap(tuples.toSeq: _*)
      }
      

      由于 Map[A,B] 具有到 TraversableOnce[Tuple2[A, B]] 的隐式路径,因此以下工作:

      scala> Map("b" -> 3, "c" -> 3, "a" -> 5).toSortedMap
      res6: scala.collection.immutable.SortedMap[String,Int] = Map(a -> 5, b -> 3, c -> 3)
      

      它甚至可以处理 Tuple2 的列表,类似于 toMap:

      scala> List(("c", 1), ("b", 3),("a", 6)).toSortedMap
      res7: scala.collection.immutable.SortedMap[String,Int] = Map(a -> 6, b -> 3, c -> 1)
      

      【讨论】:

        【解决方案6】:

        由于实现中的内部数据结构完全不同,因此无论如何您都必须一个接一个地添加元素。所以,明确地做:

        val m = Map(1 -> "one")
        
        var t = scala.collection.immutable.TreeMap[Int,String]()
        t ++= m
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多