1

I am fairly new to Scala, and would like to know if it is possible for a match to execute multiple matching cases at once. Without getting into too much detail, I am basically working on a function that "scores" a certain piece of text according to various traits; these traits can overlap, and multiple traits can be true for one given string.

To illustrate what I want in code, it would look something like this:

Say we have a String, str, with a value of "Hello World". I would like something along the lines of the following:

str match {
    case i if !i.isEmpty => 2
    case i if i.startsWith("world") => 5
    case i if i.contains("world") => 3
    case _ => 0
}

I would like the above code to trigger both the first and third conditions, effectively returning both 2 and 3 (as a tuple or in any other way).

Is this possible?

Edit: I know this can be done with a chain of if's, which is the approach I took. I'm just curious if something like the above implementation is possible.

4
  • As far as i'm concerned pattern matching only aplies to 1st correct case. Commented Sep 14, 2015 at 8:37
  • 1
    @Haito Yup... That's why I was wondering if there is any way that I'm not familiar with to make something like this work. Commented Sep 14, 2015 at 8:38
  • 3
    It is not possible. What would the return type be? You could use something like a List[(String => Boolean, Int)] and then use predicateList.collect {case (p, i) if p(myWordToTest) => i} Commented Sep 14, 2015 at 8:42
  • I ended up doing ((if (!i.isEmpty) 2) :: (if (i.startsWith("world")) 5) :: (if (i.contains("world")) 3) :: Nil) map {case i: Int => i case _ => 0} sum but wanted to see if there was a more elegant way. @Marth I'd have expected the return types to possibly be a Tuple, if something like that was possible. Commented Sep 14, 2015 at 8:51

2 Answers 2

2

You can turn your case statements to functions

val isEmpty = (str: String) => if ( !str.isEmpty) 2 else 0
val startsWith = (str: String) => if ( str.startsWith("world"))  5  else 0
val isContains = (str: String) => if (str.toLowerCase.contains("world")) 3  else 0

val str = "Hello World"

val ret = List(isEmpty, startsWith, isContains).foldLeft(List.empty[Int])( ( a, b ) =>  a :+ b(str)   )

ret.foreach(println)
//2
//0
//3

You can filter the 0 values with filter

 val ret0 = ret.filter( _ > 0)
 ret0.foreach(println)
Sign up to request clarification or add additional context in comments.

Comments

1

Please, consider this solution:

val matches = Map[Int, String => Boolean](2 -> {_.isEmpty}, 3 -> {_.contains("world")}, 5 -> {_.startsWith("world")})
val scores = matches.filter {case (k, v) => v(str)}.keys

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.