4

I have a Map[String,Seq[String]] and want to basically covert it to a Map[String,String] since I know the sequence will only have one value.

2
  • The operation is called "map" (not to be confused with the Map ADT). What has been tried? Commented Sep 18, 2012 at 17:35
  • Looks like someone asked a very similar question back in january: stackoverflow.com/questions/8914954/… Commented Sep 18, 2012 at 18:36

4 Answers 4

4

Someone else already mentioned mapValues, but if I were you I would do it like this:

scala> val m = Map(1 -> Seq(1), 2 -> Seq(2))
m: scala.collection.immutable.Map[Int,Seq[Int]] = Map(1 -> List(1), 2 -> List(2))

scala> m.map { case (k,Seq(v)) => (k,v) }
res0: scala.collection.immutable.Map[Int,Int] = Map(1 -> 1, 2 -> 2)

Two reasons:

  1. The mapValues method produces a view of the result Map, meaning that the function will be recomputed every time you access an element. Unless you plan on accessing each element exactly once, or you only plan on accessing a very small percentage of them, you don't want that recomputation to take place.

  2. Using a case with (k,Seq(v)) ensures that an exception will be thrown if the function ever sees a Seq that doesn't contain exactly one element. Using _(0) or _.head will throw an exception if there are zero elements, but will not complain if you had more than one, which will likely result in mysterious bugs later on when things go missing without errors.

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

Comments

3

You can use mapValues().

scala> Map("a" -> Seq("aaa"), "b" -> Seq("bbb"))
res0: scala.collection.immutable.Map[java.lang.String,Seq[java.lang.String]] = M
ap(a -> List(aaa), b -> List(bbb))

scala> res0.mapValues(_(0))
res1: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map(a
-> aaa, b -> bbb)

1 Comment

It's idiomatic to write .head instead of (0)
0

I think I got it by doing the following:

mymap.flatMap(x => Map(x._1 -> x._2.head))

1 Comment

This is a start. Consider putting it in the post itself. However it can be done simpler and more efficiently with a normal map (or other specialized function).
0

Yet another suggestion:

m mapValues { _.mkString }

This one's agnostic to whether the Seq has multiple elements -- it'll just concatenate all the strings together. If you're concerned about the recomputation of each value, you can make it happen up-front:

(m mapValues { _.mkString }).view.force

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.