Pattern Matching

    We use pattern matching when we want to perform different computations based on some match or condition.

    If you are familiar with switch statements, this is similar but a little more powerful.

    Types of Pattern Matching Techniques

    There are different types of pattern-matching techniques:

    1. Wildcard Pattern

    Wildcard pattern is referred to as the condition which is executed if all else fails. This is usually marked using “_” (underscore symbol).

    val list = List("One", "Two", "Three")
    
    list match {
    
     case Nil => "Star Pattern"
    
     case _ => "Wild card Pattern"
    
    }

    Output

    val list: List[String] = List(One, Two, Three)
    
    val res0: String = Wild card Pattern

    2. Variable Pattern

    val message = "Hello ! What's up "
    
    message match {
     case greet: String => s"$greet TGB Users"
    }

    Output

    val message: String = "Hello ! What's up "
    
    val res1: String = Hello ! What's up  TGB Users

    3. Constant Pattern

    val ONE: Int = 1
    val TWO: Int = 2
    val THREE: Int = 3
    
    def matcher(x: Int) {
     x match {
       case ONE => println("one")
       case TWO => println("two")
       case THREE => println("three")
       case _ => println("many : Match case for Wildcard Pattern")
     }
    }
     
    matcher(ONE)
    matcher(TWO)

    Output

    val ONE: Int = 1
    val TWO: Int = 2
    val THREE: Int = 3
    
    def matcher(x: Int): Unit
    one
    two

    4. Constructor Pattern

    case class Pet(name: String, animal: String)
    
    val listOfPets = List(Pet("Ginger", "Dog"),
     Pet("boo", "Cat"),
     Pet("Tommy", "Dog"),
     Pet("Bow", "Dog"))
    
    listOfPets.map {
     case Pet(name, "Dog") => s"$name is a Dog"
     case _ => "The pet is not a Dog :)"
    }

    Output

    class Person
    
    class Pet
    
    val listOfPets: List[Pet] = List(Pet(Ginger,Dog), Pet(boo,Cat), Pet(Tommy,Dog), Pet(Bow,Dog))
    
    val res4: List[String] = List(Ginger is a Dog, The pet is not a Dog :), Tommy is a Dog, Bow is a Dog)

    5. Sequence Pattern

    def getListType(x: List[Any]) = {
    
     x match {
       case Nil => "Got an Empty List"
       case List(10, _, _) => "Got a size three list, starting with 10"
       case List(1, _*) => "Got a list starting with one"
       case _ => "Fallen in default case"
     }
    }
    
    getListType(List())
    getListType(List(1, 2, 3))
    getListType(List(10, 2, 0))
    getListType(List(3, 4, 7, 1))

    Output

    def getListType(x: List[Any]): String
    
    val res5: String = Got an Empty List
    
    val res6: String = Got a list starting with one
    
    val res7: String = Got a size three list, starting with 10
    
    val res8: String = Fallen in default case

    6. Tuple Pattern

    val zippedValue1 = ("Gaurav", 1, 25)
    
    val zippedValue2 = ("Mohit", 1, "25")
    
    def decode(details: Any) = {
    
     details match {
    
       case (name: String, sr: Int, age: Int) => s"$name-------$sr-------$age"
    
       case (name: String, sr: Int, age: String) => s"$name--------$sr"
    
     }
    
    }
    
    decode(zippedValue1)
    
    decode(zippedValue2)

    Output:

    val zippedValue1: (String, Int, Int) = (Gaurav,1,25)
    val zippedValue2: (String, Int, String) = (Mohit,1,25)
    def decode(details: Any): String
    val res9: String = Gaurav-------1-------25
    val res10: String = Mohit--------1

    7. Typed Pattern

    def returnWhatYouGet(valType: Any) = {
    
     valType match {
    
       case s: String => s"you gave me this string: $s"
    
       case i: Int => s"thanks for the int: $i"
    
       case f: Float => s"thanks for the float: $f"
    
       case a: Array[Int] => s"an array of int: ${ a.mkString(",") }"
    
       case as: Array[String] => s"an array of strings: ${ as.mkString(",") }"
    
       case d: Pet => s"dog: ${ d.name }"
    
       case list: List[_] => s"thanks for the List: $list"
    
       case m: Map[_, _] => m.toString
    
     }
    
    }
    
    returnWhatYouGet("Hi")
    
    returnWhatYouGet(1)
    
    returnWhatYouGet(listOfPets.head)

    Output

    def returnWhatYouGet(valType: Any): String
    
    val res11: String = you gave me this string: Hi
    
    val res12: String = thanks for the int: 1
    
    val res13: String = dog: Ginger

    8. Using Pattern Guard

    abstract class Notification
    
    case class Email(sender:String, title: String, body: String) extends Notification
    case class SMS(caller: String, message: String) extends Notification
    case class VoiceRecording(contactName: String, link: String) extends Notification
    
     
    def showImportantNotification(notification: Notification, importantPeopleInfo: Seq[String]): String = {
    
     notification match {
    
       case Email(email, _, _) if importantPeopleInfo.contains(email) =>
    
         "You got an email from special someone!"
    
       case SMS(number, _) if importantPeopleInfo.contains(number) =>
    
         "You got an SMS from special someone!"
    
       case other => "Unknown Service"
          // nothing special, delegate to our original showNotification function
     }
    }
    
    val importantPeopleInfo = Seq("867-5309", "jenny@gmail.com")
    val someSms = SMS("867-5309", "Are you there?")
    val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123")
    val importantEmail = Email("jenny@gmail.com", "Drinks tonight?", "I'm free after 5!")
    val importantSms = SMS("867-5309", "I'm here! Where are you?")
     
    println(showImportantNotification(someSms, importantPeopleInfo))
    println(showImportantNotification(someVoiceRecording, importantPeopleInfo))
    println(showImportantNotification(importantEmail, importantPeopleInfo))
    println(showImportantNotification(importantSms, importantPeopleInfo))

    Output

    class Notification
    
    
    class Email
    
    class SMS
    
    class VoiceRecording
    
     
    def showImportantNotification(notification: Notification, importantPeopleInfo: Seq[String]): String
    
     
    val importantPeopleInfo: Seq[String] = List(867-5309, jenny@gmail.com)
    
    val someSms: SMS = SMS(867-5309,Are you there?)
    
    val someVoiceRecording: VoiceRecording = VoiceRecording(Tom,voicerecording.org/id/123)
    
    val importantEmail: Email = Email(jenny@gmail.com,Drinks tonight?,I'm free after 5!)
    
    val importantSms: SMS = SMS(867-5309,I'm here! Where are you?)
    
     
    You got an SMS from special someone!
    
    Unknown Service
    
    You got an email from special someone!
    
    You got an SMS from special someone!

    9. Sealed Class pattern

    sealed abstract class Furniture
    
    case class Couch() extends Furniture
    
    case class Chair() extends Furniture
    
    
    def findPlaceToSit(piece: Furniture): String = piece match {
    
     case a: Couch => "Lie on the couch"
    
     case b: Chair => "Sit on the chair"
    
    }

    Output

    class Furniture
    class Couch
    class Chair
    
    def findPlaceToSit(piece: Furniture): String