Съпоставянето на шаблони е много полезна функция в езиците за програмиране. Но в Scala това е много мощна функция за разлика от C, C++, Java.

Съпоставянето на шаблони е като случай на превключване в Java и т.н., но когато става дума за език за програмиране Scala, виждаме много начини за използването му. Наскоро, когато работех върху списъци, трябваше да изпълнявам рекурсивни функции върху списъци, проучих много начини, по които съпоставянето на шаблони може да се извърши върху колекции на Scala. В тази статия ще проучим следните типове съвпадение на шаблони:

1) Променлив модел

2) Тип модел

3) Буквен модел

4) Модел на интерполирани низове

5) Модел на „стабилни“ идентификатори

6) Шаблон за конструктор

7) Модел на кортежи

8) Модел на екстрактори

Нека се потопим в горните типове:

1) Променлив модел:

Нека разгледаме примера по-долу:

case _ => println("Ok, I don't bother what value is, I just matched it with any character")

Този модел се нарича шаблон за заместващи символи, моделът на променлива също работи по същия начин и допълнително позволява да се обвърже стойност към променлива, за да се използва по-късно в израза. Вижте примера по-долу за модел на променлива:

def variablePatternType(value: Any) = {
  value match{
    case city => println(s"Welcome to $city")
  }
}
variablePatternType("Bengaluru")

2) Типов модел:

Както видяхме в модела на променливата, той ни позволява да свържем „стойност“ към променлива, в случай на шаблони на типове, типът е обвързан със стойност. Например в примерите по-долу customerName: String е въведен модел. Ако въведеното от потребителя е различно от низ, тогава се хвърля изключение.

val personName = "David"
personName match {
  case customerName: String => println(s"Hello $customerName")
  case _ => throw new IllegalArgumentException("Received incorrect value")
}

3) Литерален модел:

Добре, какво е буквално? Литералът представлява всяка фиксирана стойност, присвоена на променлива. Някои хора наричат ​​този модел постоянен модел. Нека разгледаме примера по-долу:

val cityName = "Delhi"
cityName match{
  case "Delhi" => println(s"Welcome to $cityName")
  case _ => throw new IllegalArgumentException(s"No value matched")
}

4) Интерполиран модел на низове:

Съпоставянето на шаблон на интерполирани низове не е нищо друго освен съпоставяне на модела на разделени със специален символ или с някакъв разделител. С прости думи, той разделя по-големия низ въз основа на разделител и проверява за този модел. Разгледайте примера по-долу:

val countryStateCode = "IN::KA"
def interpolatedStringPatternMatch(countryStateCode: String) = {
  countryStateCode match {
    case s"${countryCode}::${stateCode}" => println(s"Country Code=$countryCode, State Code=$stateCode")
    case _ => throw new IllegalArgumentException(s"Invalid pattern")
  }
}
interpolatedStringPatternMatch(countryStateCode) //Country Code=IN, State Code=KA

В горния пример входът е разделен с разделител „::“ и ако той присъства във входа, значи е съпоставен.

5) Образец на „стабилни“ идентификатори:

Стабилният идентификатор съответства на всяка дадена стойност стойност1, така че стойност2 === стойност1. В шаблона на променлива стойността се съпоставя с всяка стойност, но в модела на стабилен идентификатор стойността трябва да съвпада точно. Синтактично този шаблон не започва със стандартни малки букви, но името на променливата трябва да бъде оградено в обратен кавич (`x`), след което се счита за стабилен шаблон на идентификатор.

Вижте примера по-долу:

def stableIdentifierPattern(value1:Int,value2:Int) = value1 match{
  case `value2` => println(s"Both values are equal")
  case _ => println(s"Both values are not equal")
}
stableIdentifierPattern(5,5) //Both values are equal
stableIdentifierPattern(5,10) //Both values are not equal

В горния пример съвпадението е успешно само ако стойност1 и стойност2 са равни.

6) Конструктор модел:

Моделът на конструктора ви позволява да извършите съвпадение с конструктор на клас case. Нека да разгледаме примера по-долу:

case class User(name: String, city:String,postalCode:String)

def constructorPattern(user:User) = {
  user match {
    case User("Dale", personCity, "560008") => println(s"Dale lives in $personCity")
    case _ => throw new IllegalArgumentException(s"Invalid User")
  }
}
constructorPattern(User("Dale","Bengaluru","560008")) //Dale lives in Bengaluru
constructorPattern(User("David","Bengaluru","560008")) //Invalid User

Както е показано в горния пример, можете да зададете константи или променливи модели в шаблона на конструктора.

7) Tuple Pattern:

Моделът на кортежа е псевдоним на шаблона на конструктора в scala. Моделът на кортежа може да бъде съпоставен, както е показано в примера по-долу, и стойността на всеки елемент може да бъде достъпна:

def tuplePattern(values: Any) = values match {
  case (val1,val2,val3) => println(s"This is 3-element tuple having values $val1,$val2,$val3")
  case _ => throw new IllegalArgumentException(s"Invalid tuple pattern")
}
tuplePattern(("A","B","C")) //This is 3-element tuple having values A,B,C
tuplePattern(("A","B","C","D")) //Invalid tuple pattern

Ако не се интересувате от стойността на елемента, използвайте заместващия знак _.

8) Модел за извличане:

Шаблонът за извличане се прилага към обект, който има метод, наречен unapply или unapplySeq, който съответства на шаблона. Моделът на екстрактор понякога се нарича модел на деструктор.

import scala.util.Random
  object OrderId{
    def apply(name:String) = s"$name-${Random.nextLong()}"
    def unapply(orderId: String) = {
      val customerOrderArray = orderId.split("-")
      if (customerOrderArray.tail.nonEmpty) Some(customerOrderArray.head) else None
    }
  }
  //OrderId.apply("David")
  val orderId = OrderId("David") //David-1066514660868982191
  orderId match{
    //OrderId.unapply(order1Id), extracting name from orderId
    case OrderId(name) => println(name)   //David
    case _ => throw new IllegalArgumentException(s"Could not extract order Id")
  }

Когато броят на стойностите за извличане не е фиксиран и бихме искали да върнем произволен брой стойности в зависимост от входа, в такъв случай можете да дефинирате екстрактори с метода unapplySeq. Често срещан пример за това е деконструирането на списък:

def sum(numbersList:List[Int]):Int = numbersList match{
  case Nil => 0
  case head :: tail => head + sum(tail)
}

Това, което се случва тук, е, че списъкът се деконструира на глава и опашка с помощта на шаблона „глава :: опашка“. “ :: ” се извиква като деконструиращ оператор.

Ако имате някакви въпроси, моля, оставете ги в коментар.

Приятно учене!!!!