3

say I have a map in Scala - key: String, value: String.

Is there an easy way to get the arrays of keys and values in corresponding order? E.g. the i-th element of the key array should be the key related to the i-th value of the values array.

What I've tried is iterating through the map and getting them one by one:

valuesMap.foreach{keyVal => keys.append(keyVal.1); values.append(keyVal.2); // the idea, not the actual code

Is there a simplier way?

The question could probably be asked: is there any way to guarantee a specific order of map.keys/map.values?

For example, when generating an SQL query it may be convenient to have arrays of column names and values separately, but with the same order.

6
  • 3
    You do know that Map, as well as Set, has no well defined order, right? Commented Aug 29, 2014 at 12:04
  • om-nom-nom, I do, that's why I'm asking this question. To put it differently: getting all the keys as a set (or even as an array) does not guarantee any order (possibly unless I explicitly ask for one). Hence I doubt there's any guarantee that i-th key will map to i-th value Commented Aug 29, 2014 at 12:22
  • 1
    then how about using a proper Map implementation? I don't think your problem is solveable, in case you tied somehow to a generic Map Commented Aug 29, 2014 at 12:23
  • om-nom-nom, seems like LinkedHashMap solves the problem, thank you once again Commented Aug 29, 2014 at 12:27
  • Why don't you just look up the values array given the keys array? val keys = valuesMap.keySet.toSeq; val values = keys.map{key=>valuesMap(key)} Sure, lots of lookups, but there are hidden lookups in other ways of retrieving the values anyway. Commented Aug 29, 2014 at 14:44

2 Answers 2

7

You can use toSeq to get a sequence of pairs that has a fixed order, and then you can sort by the key (or any other function of the pairs). For example:

scala> val pairs = Map(3 -> 'c, 1 -> 'a, 4 -> 'd, 2 -> 'b).toSeq.sortBy(_._1)
res0: Seq[(Int, Symbol)] = ArrayBuffer((1,'a), (2,'b), (3,'c), (4,'d))

Now you can use unzip to turn this sequence of pairs into a pair of sequences:

scala> val (keys, vals) = pairs.unzip
keys: Seq[Int] = ArrayBuffer(1, 2, 3, 4)
vals: Seq[Symbol] = ArrayBuffer('a, 'b, 'c, 'd)

The keys and values will line up, and you've only performed the sorting operation once.

Sign up to request clarification or add additional context in comments.

1 Comment

It's not guaranteed to be a fixed order until after the sortBy, I think? Or, as a weaker statement, the order returned by toSeq is irrelevant because you immediately sort it.
1

If all you want is that key- and value-lists line up, then it's really easy:

val (keys, vals) = yourMap.toSeq.unzip

All the information of the original map is preserved the ordering. You can get it back like so

val originalMap = (keys zip values).toMap
assert(originalMap == yourMap)

Comments

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.