I want to access to the case value in the case block
val a = "hello"
a match {
case "hello" | "Hi" =>
println("hello") // how can I access the right case value? Hello or Hi?
case _ =>
print("NA")
}
You can reference the matched value like so:
a match {
case str # ("hello" | "Hi") => println(str)
case _ => print("NA")
}
Another way could be -
a match {
case str if str == "hello" | str == "Hi" => println(str)
case _ => println("NA")
}
Related
Can I combine the following two cases into one case clause since they both do the same thing?
e match {
case "hello" => e + "world"
case "hi" => e + "world
}
Also, what about if I want to match using startsWith e.g.,
e match { case e.startsWith("he") | e.startsWith("hi") => ... }
Yes you can simply use or (|) to match one of the pattern,
scala> "hi" match { case "hello" | "hi" => println("fantastic") case _ => println("very very bad")}
fantastic
scala> "hello" match { case "hello" | "hi" => println("fantastic") case _ => println("very very bad")}
fantastic
scala> "something else" match { case "hello" | "hi" => println("fantastic") case _ => println("very very bad")}
very very bad
You can also use regex to pattern match, especially useful when there are many criterias to match,
scala> val startsWithHiOrHello = """hello.*|hi.*""".r
startsWithHiOrHello: scala.util.matching.Regex = hello.*|hi.*
scala> "hi there" match { case startsWithHiOrHello() => println("fantastic") case _ => println("very very bad")}
fantastic
scala> "hello there" match { case startsWithHiOrHello() => println("fantastic") case _ => println("very very bad")}
fantastic
scala> "non of hi or hello there" match { case startsWithHiOrHello() => println("fantastic") case _ => println("very very bad")}
very very bad
Refer to Scala multiple type pattern matching and Scala match case on regex directly
Looking at this function as an example:
def receive = {
case "test" => log.info("received test")
case _ => log.info("received unknown message")
}
What object is being matched on? On the right hand side of the arrows, how can I refer to the object being matched on?
You can do it with an if-guard:
def receive: String => Unit = {
case str if str == "test" => println(str)
case _ => println("other")
}
Option("test").map(receive) // prints "test"
Option("foo").map(receive) // prints "other"
Note that if you have an object that you want to refer to, then stuff like e.g. foo: Foo(s) won't work (foo: Foo will, but then you lose the reference to Foo's value s). In that case you need to use the # operator:
case class Foo(s: String)
def receive: Foo => Unit = {
case foo#Foo(s) => println(foo.s) // could've referred to just "s" too
case _ => println("other")
}
Option(Foo("test")).map(receive) // prints "test"
If you want a case to match on anything, and have a reference to it, use a variable name instead of underscore
def receive = {
case "test" => log.info("received test")
case other => log.info("received unknown message: " + other)
}
match (str) {
case "String1" => ???
case "String2" => ???
}
This is case sensitive matching. How to write case insensitive matching? I know I can call toLowerCase for each branch, but I want more elegant solution.
Basic approach:
You could use Pattern Guards and Regular Expressions
str match {
case s if s matches "(?i)String1" => 1
case s if s matches "(?i)String2" => 2
case _ => 0
}
Sophisticated method:
Implicits with String Interpolation and Regex
implicit class CaseInsensitiveRegex(sc: StringContext) {
def ci = ( "(?i)" + sc.parts.mkString ).r
}
def doStringMatch(str: String) = str match {
case ci"String1" => 1
case ci"String2" => 2
case _ => 0
}
Some example usage in the REPL:
scala> doStringMatch("StRINg1")
res5: Int = 1
scala> doStringMatch("sTring2")
res8: Int = 2
Easy solution:
val str = "string1"
str toUpperCase match (str) {
case "STRING1" => ???
case "STRING2" => ???
}
Another approach that does not depend on regexes or interpolaters:
implicit class StringExtensions(val s: String) extends AnyVal {
def insensitive = new {
def unapply(other: String) = s.equalsIgnoreCase(other)
}
}
val test1 = "Bye".insensitive
val test2 = "HELLo".insensitive
"Hello" match {
case test1() => println("bad!")
case test2() => println("sweet!")
case _ => println("fail!")
}
Here is another way using interpolaters but no regex:
implicit class StringInterpolations(sc: StringContext) {
def ci = new {
def unapply(other: String) = sc.parts.mkString.equalsIgnoreCase(other)
}
}
"Hello" match {
case ci"Bye" => println("bad!")
case ci"HELLO" => println("sweet!")
case _ => println("fail!")
}
The above can also be used to pattern match inside case classes e.g.:
case class Dog(name: String)
val fido = Dog("FIDO")
fido match {
case Dog(ci"fido") => "woof"
case _ => "meow :("
}
Is there an easy/best way to get a BitSet I can pattern match like a list?
val btst = BitSet(1,2,3,4)
btst match {
...
case head :: tail => tail
}
By definition a set is an unordered collection, and pattern matching over such one is error-prone. Convert it to list if you want to... Also, you should not rely on head and tail to always return the same thing.
A BitSet is ordered, but extractorless.
Edit: but not humorless.
object |<| {
def unapply(s: BitSet): Option[(Int, BitSet)] =
if (s.isEmpty) None
else Some((s.head, s.tail))
}
def flags(b: BitSet) = b match {
case f"5 || 10" => println("Five and dime") // alas, never a literal
case 5 |<| any => println(s"Low bit is 5iver, rest are $any")
case i |<| any => println(s"Low bit is $i, rest are $any")
case _ => println("None")
}
def dump(b: BitSet) = println(b.toBitMask.mkString(","))
val s = BitSet(5, 7, 11, 17, 19, 65)
dump(s)
// ordinary laborious tests
s match {
case x if x == BitSet(5) => println("Five")
case x if x == BitSet(5,7,11,17,19,65) => println("All")
case x if x(5) => println("Five or more")
case _ => println("None")
}
// manually matching on the mask is laborious
// and depends on the bit length
s.toBitMask match {
case Array(2L) => println("One")
case Array(657568L) => println("First word's worth")
case Array(657568L, _) => println("All")
case _ => println("None")
}
// or truncate for special case
s.toBitMask(0) match {
case 2L => println("One")
case 657568L => println("First word's worth")
case _ => println("None")
}
How do you code a function that takes in a block of code as a parameter that contains case statements? For instance, in my block of code, I don't want to do a match or a default case explicitly. I am looking something like this
myApi {
case Whatever() => // code for case 1
case SomethingElse() => // code for case 2
}
And inside of my myApi(), it'll actually execute the code block and do the matches.
You have to use a PartialFunction for this.
scala> def patternMatchWithPartialFunction(x: Any)(f: PartialFunction[Any, Unit]) = f(x)
patternMatchWithPartialFunction: (x: Any)(f: PartialFunction[Any,Unit])Unit
scala> patternMatchWithPartialFunction("hello") {
| case s: String => println("Found a string with value: " + s)
| case _ => println("Found something else")
| }
Found a string with value: hello
scala> patternMatchWithPartialFunction(42) {
| case s: String => println("Found a string with value: " + s)
| case _ => println("Found something else")
| }
Found something else
This should suffice to explain it: A Tour of Scala: Pattern Matching