Thursday, December 30, 2010

How to convert two Scala Lists into a Map

Update:

Since I posted this 24 hours ago, no fewer than 13 lovely people have left comments to let me know that this is actually far, far easier than I thought. There is a function on the List class (since 2.8.0, I think someone said), inherited from TraversableOnce, called toMap() which, if the sequence contains Tuple2s, will make a Map from them.

So the ideal solution is simply:
(keys zip values) toMap
Now the question is: How come everyone else knows about this and I didn't? :(

A couple of people also mentioned that you don't need to convert a List into an Array to be able to pass it into a var args method (but you still need the funky noise). Handy!

Thanks, everyone.


Original Post...

Not sure if this will ever be of use to anyone else, but I thought I'd put it out there just in case.

Problem:
You have a List/Seq of keys and a List/Seq of values, with the key at index n in one list matching the value at index n in the other. But what you really want is to convert them into a Map.

Solution:
Map(keys.zip(values).toArray: _*)

Explanation:
The steps here are:
  1. "Zip" the keys list with the values list, which creates a List of Tuple2 objects
  2. Convert the list of Tuples to an Array of Tuples. This is necessary because the Map object, which extends MapFactory, doesn't have any apply() methods that deal with lists but only the one that accepts a var args parameter of Tuple2s.
  3. Add this funky noise ": _*" which tells Scala to pass the Array as multiple varargs parameters, rather than trying to pass the whole Array as the first parameter.

3 comments:

  1. Hello Graham,
    thanks for the post. It shows how terse and elegant the Scala language is.
    It's not exactly in the topic, but, trying to understand the code I read the ScalaDoc for the zip(), that signs:

    def zip[A1 >: A,B,That](that: Iterable[B])(implicit bf: scala.collection.generic.CanBuildFrom[Repr,(A1, B),That]): That

    would you please help us to read/understand this?
    Thank you.

    ReplyDelete
  2. Hi Marcos,

    I've created a blog post about Scala's CanBuildFrom class in response to your question.
    I hope it answers what you're looking for.

    Cheers,

    Graham.

    ReplyDelete
  3. It looks much easier to convert Map into List in Java. Thanks for sharing this nice tip.

    ReplyDelete