avy
avy

Reputation: 437

Convert Array[(String,String)] to Map[String,String] keeping the order of keys in Scala

I am trying to convert Array[(String,String)] to Map[String,String] in scala.

I am trying toMap to convert to map.

Problem : It is changing the order of values.

Expectation : Order should not be changed.

Thanks

Upvotes: 2

Views: 3376

Answers (3)

Aditya Chopra
Aditya Chopra

Reputation: 80

I think this will work...

LinkedHashMap class implements mutable maps using a hashtable. The iterator and all traversal methods of this class visit elements in the order they were inserted.

scala> val arr = Array(("something","else"),("foo","a"),("bar","b"),("some","c"),("a1","b1"),("a2","b2"),("a3","b3"),("a4","b4"),("a5","b5"),("a6","c6"))
arr: Array[(String, String)] = Array((something,else), (foo,a), (bar,b), (some,c), (a1,b1), (a2,b2), (a3,b3), (a4,b4), (a5,b5), (a6,c6))

scala> val testMap =  scala.collection.mutable.LinkedHashMap[String,String]()
testMap: scala.collection.mutable.LinkedHashMap[String,String] = Map()

arr.foreach(x=> testMap += (x._1 ->x._2))

scala> testMap
res1: scala.collection.mutable.LinkedHashMap[String,String] = Map(something -> else, foo -> a, bar -> b, some -> c, a1 -> b1, a2 -> b2, a3 -> b3, a4 -> b4, a5 -> b5, a6 -> c6)

Upvotes: 3

Marko Švaljek
Marko Švaljek

Reputation: 2101

After Comments:

It looks like the naive approach would not work in a sense that the order of the keys would be preserved. Here is a very useful test script from

andrey-tyukin

  for (s <- 1 until 100) {
    val keys = (1 to s).map(_.toString).toList
    val arr: Array[(String, String)] = keys.map { x => (x, x) }.toArray
    val m = arr.toMap
    val newKeysOrder = m.map(_._1).toList println (s + ": " + (keys == newKeysOrder))
  }

Basically it shows that the this approach is no good.

Array(("foo","a"), ("bar", "b"), ("baz", "c")).toList.toMap

I would however advise to avoid mutable data structures.

New Anser:

I would just use another simple construct from scala.collection.immutable.ListMap :

val m = ListMap(arr:_*)

And here is a script that tests if it's o.k. basically it's true for first 100 ints

  for (s <- 1 until 100) {
    val keys = (1 to s).map(_.toString).toList
    val arr: Array[(String, String)] = keys.map { x => (x, x) }.toArray
    val m = ListMap(arr: _*)
    val newKeysOrder = m.keys.toList
    println(s + ": " + (keys == newKeysOrder))
  }

Upvotes: 0

Manoj Kumar Dhakad
Manoj Kumar Dhakad

Reputation: 1892

You can use ListMap which implements immutable maps by using a list-based data structure.

ListMap maintains insertion order and returns ListMap.

1.Create an array

 val arr=Array(("a","Alice"),("b","Bob"),("c","Cat"),("d","Dog"))

2.Create ListMap

import scala.collection.immutable._
val listMap=arr.foldLeft(ListMap[String,String]())((prev,next)=>prev+(next._1->next._2))

3.It will produce below output

listMap: scala.collection.immutable.ListMap[String,String] = Map(a -> Alice, b -> Bob, c -> Cat, d -> Dog)

Upvotes: 0

Related Questions