0

For a long listing of cases which return a value within a limited domain, how to reduce the otherwise growing number of case declarations ? For instance consider

"abc" match {
  case "a"   => 1
  case "ab"  => 1
  case "aw"  => 2
  case "hs"  => 2
  case "abc" => 1
  case _     => 0
}

Tried a Map[Set[String],Int] where

val matches = Map( Set("a","ab","abc") -> 1, Set("aw","hs") -> 2 )

and defined

def getMatch(key: String, m: Map[Set[String],Int]) = {
  val res = m.keys.collectFirst{ case s if s(key) => m(s) }
  res.getOrElse(0)
}

Are there simpler and/or more efficient approaches to this ?

elm
  • 20,117
  • 14
  • 67
  • 113
  • Well... For cases similar to this why do you want to take the performance hit by adding a need for iterating through all the keys ? Why don't just use `Map`s themselves ? Just have `Map[ String, Int ]` and put all your "cases" inside. – sarveshseri Feb 25 '15 at 07:49
  • Many Thanks for the idea, this is also a working solution, although reducing the repetitiveness in the values is also within the scope of the enquiry. – elm Feb 25 '15 at 07:58

3 Answers3

6

You can group your cases:

"abc" match {
  case "a" | "ab" | "abc"   => 1
  case "aw" | "hs"  => 2
  case _     => 0
}
Mariusz Nosiński
  • 1,308
  • 9
  • 10
2

You can create your own matchers like this:

class InSet[T](set: Set[T]) { 
  def unapply(t: T) = set.find(t) 
}
val set1 = new InSet(Set("a","ab","abc"))
val set2 = new InSet(Set("aw","hs"))
"aw" match { 
  case set1(a) => "1, " + a
  case set2(a) => "2, " + a
  case _ => "3"
}

The good thing about this is that it makes it easy to create and apply very different matchers.

thoredge
  • 12,237
  • 1
  • 40
  • 55
1

You can shift the complexity a bit by doing this:

 val m = matches.flatMap { case (xs,i) => xs.map(_ -> i) }.withDefaultValue(0)

 m("abc")  // 1
 m("z")    // 0

Thus avoiding the need to call things through your getMatch function. Possibly faster too since you upfront the work instead of iterating through the keys every time you need call getMatch.

dhg
  • 52,383
  • 8
  • 123
  • 144