6

I'm fairly new to Scala, but I'm doing my exercises now.
I have a string like

"A>Augsburg;B>Berlin"
. What I want at the end is a map

val mymap = Map("A"->"Augsburg", "B"->"Berlin")

What I did is:

val st = locations.split(";").map(dynamicListExtract _)
with the function
private def dynamicListExtract(input: String)  = {
    if (input contains ">") {
      val split = input split ">"
      Some(split(0), split(1)) // return key , value
    } else {
      None 
    } 
  }
Now I have an
Array[Option[(String, String)
How do I elegantly convert this into a Map[String, String]

Can anybody help? Thanks

5 Answers 5

12

Just change your map call to flatMap:

scala> sPairs.split(";").flatMap(dynamicListExtract _)
res1: Array[(java.lang.String, java.lang.String)] = Array((A,Augsburg), (B,Berlin))

scala> Map(sPairs.split(";").flatMap(dynamicListExtract _): _*)
res2: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map((A,Augsburg), (B,Berlin))

For comparison:

scala> Map("A" -> "Augsburg", "B" -> "Berlin")
res3: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map((A,Augsburg), (B,Berlin))
Sign up to request clarification or add additional context in comments.

2 Comments

Another trick to know is that Map's ++ method takes a TraversaleOnce so you could use st like so: Map[String, String]() ++ st.flatMap(n => n). Randal's way is better.
Thank you for your fast answer. My problem was not the flatMap instead of map (although this is also helpful), but not knowing the <pre><code>Map(Seq(A,B) : _*) </pre></code> constructor.
9

In 2.8, you can do this:

val locations = "A>Augsburg;B>Berlin"
val result = locations.split(";").map(_ split ">") collect { case Array(k, v) => (k, v) } toMap

collect is like map but also filters values that aren't defined in the partial function. toMap will create a Map from a Traversable as long as it's a Traversable[(K, V)].

1 Comment

I think that was I was actually looking for. Thank you!
3

It's also worth seeing Randall's solution in for-comprehension form, which might be clearer, or at least give you a better idea of what flatMap is doing.

Map.empty ++ (for(possiblePair<-sPairs.split(";"); pair<-dynamicListExtract(possiblePair)) yield pair)

Comments

0

A simple solution (not handling error cases):

val str = "A>Aus;B>Ber"
var map = Map[String,String]()

str.split(";").map(_.split(">")).foreach(a=>map += a(0) -> a(1))

but Ben Lings' is better.

Comments

0
val str= "A>Augsburg;B>Berlin"

Map(str.split(";").map(_ split ">").map(s => (s(0),s(1))):_*)

--or--

str.split(";").map(_ split ">").foldLeft(Map[String,String]())((m,s) => m + (s(0) -> s(1)))

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.