0

I currently have the following, which works, but I'm very new to Scala and I'm wondering if there's a better way to do it.

val utmcsr = """.*utmcsr=(.*)""".r
val utmcmd = """.*utmcmd=(.*)""".r
val utmccn = """.*utmccn=(.*)""".r
val utmctr = """.*utmctr=(.*)""".r

val utmz = "14002953.138298057.2.2.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided)"
utmz.split("""\|""").map {
        case utmcsr(s) => List("utmscr", s)
        case utmcmd(s) => List("utmcmd", s)
        case utmccn(s) => List("utmccn", s)
        case utmctr(s) => List("utmctr", s)
        case _ => ""
    }.foldLeft(Map[String,String]()) {
        (m, s) => 
            val key = s.asInstanceOf[List[String]].head
            val value = s.asInstanceOf[List[String]].tail.head
            m + (key -> value)
    }
}

My main questions are:

  1. Why do I need to parse s as an instance of List - shouldn't it already be a list?
  2. Is there a way to do this with tuples instead of lists?
  3. Is there a built-in way to do the list to map conversion?
2
  • 1
    Can you show at least one definition of extractors? e.g. utmcsr Commented Nov 22, 2013 at 16:18
  • Whoops! Added them in an edit. Thanks! Commented Nov 22, 2013 at 16:18

1 Answer 1

5

All your code can be written in the following way:

val kv = """.*(utmcsr|utmcmd|utmccn|utmctr)=(.*)""".r
// assuming you don't want to do this generally, only utmcsr ... utmctr values are accepted
// otherwise there can be something like """.*([a-z]+)=(.*)""".r
val utmz = "14002953.138298057.2.2.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided)"

utmz.split("""\|""").map {
    case kv(key, value) => key -> value
}.toMap
// Map(utmcsr -> google, utmccn -> (organic), utmcmd -> organic, utmctr -> (not%20provided))

Now answering your questions:

Why do I need to parse s as an instance of List - shouldn't it already be a list?

Because of default case -- empty string is not a List. Questions 2 and 3 demonstrated in snippet above.

P.S. if you want to silently ignore tokens that do not match kv regexp, swap map with a collect operation. Current implementation will die with MatchError

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

2 Comments

Oh! So if I returned List("", "") for the empty case, I wouldn't have had to coerce the types in the folding?
@Erty exactly (and it's easy to check)

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.