2

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

4
  • 2
    Possible duplicate of Scala Map implementation keeping entries in insertion order? Commented Mar 23, 2018 at 13:47
  • 1
    The question is nonsensical, because there is no such thing as Array[String, String], at least not with the standard definition of Array. Commented Mar 23, 2018 at 13:52
  • 2
    It's also confusing to talk about order of values in a map which is an unordered data structure (apart from special implementations such as SortedMap). Commented Mar 23, 2018 at 14:03
  • 1
    Do you mean Array[(String, String)]? Commented Mar 23, 2018 at 14:23

3 Answers 3

3

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)
Sign up to request clarification or add additional context in comments.

Comments

0

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)

Comments

0

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))
  }

5 Comments

Please read the other answers and comments before answering. This does NOT preserve order as the OP requested. Edit: Since the other post has been deleted, you obviously can't check the other answers now. But try this out on a larger collection. You will see it does not preserve order
I did try on up to 10 items there and thought it's fine ... I'll have a look at larger collection, have to commute now will give it a look in the evening. It might also be wrong answer, as far as I tried it worked.
Try this. val a = for (i <- 1 to 5; j <- 6 to 10) yield ("" + i, "" + j) val b = a.toList b.toMap res9: scala.collection.immutable.Map[String,String] = Map(4 -> 10, 5 -> 10, 1 -> 10, 2 -> 10, 3 -> 10) I think issues may occur when there are collisions
Here is another fun little script to experiment with, if you want: 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)) } For this particular choice of keys, it seems to preserve the order for tiny maps of size up to 4.
Thanks for providing the script :) at least I would like to avoid mutable then. I'll update my answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.