Я хотел бы преобразовать a Map[Int, Any]
в SortedMap
или TreeMap
. Есть ли простой способ сделать это?
Как преобразовать карту [Int, Any] в SortedMap в Scala? Или TreeMap?
Ответ 1
Предполагая, что вы используете неизменяемые карты
val m = Map(1 -> "one")
val t = scala.collection.immutable.TreeMap(m.toArray:_*)
Метод применения объекта сопутствующего объекта TreeMap
принимает повторяющиеся параметры ввода карты (которые являются экземплярами Tuple2[_, _]
соответствующих типов параметров). toArray
создает Array[Tuple2[Int, String]]
(в данном конкретном случае). : _*
сообщает компилятору, что содержимое массива должно рассматриваться как повторяющиеся параметры.
Ответ 2
Альтернативой использованию :_*
, описанной sblundy, является добавление существующей карты в пустой SortedMap
import scala.collection.immutable.SortedMap
val m = Map(1 -> ("one":Any))
val sorted = SortedMap[Int, Any]() ++ m
Ответ 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
CHALLENGE
Возможно ли отрегулировать имплициты, чтобы это сработало? Или это было бы возможно только в том случае, если as
были добавлены в Traversable
?
"foo".as[Vector]
Ответ 4
Здесь вы можете сделать это с помощью неявного класса 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)
Он даже работает над списком Tuple2s, аналогичным toMap:
scala> List(("c", 1), ("b", 3),("a", 6)).toSortedMap
res7: scala.collection.immutable.SortedMap[String,Int] = Map(a -> 6, b -> 3, c -> 1)
Ответ 5
Поскольку внутренние структуры данных в реализациях совершенно разные, вам все равно придется добавлять элементы по одному. Итак, сделайте это явно:
val m = Map(1 -> "one")
var t = scala.collection.immutable.TreeMap[Int,String]()
t ++= m
Ответ 6
Начиная с 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")