Совместимость шаблонов с нечувствительными к строкам

match (str) {
  case "String1" => ???
  case "String2" => ???
}

Это соответствие с учетом регистра. Как написать нечувствительность к регистру? Я знаю, что могу вызвать toLowerCase для каждой ветки, но я хочу более элегантное решение.

Ответы

Ответ 1

Основной подход:

Вы можете использовать Защиты шаблонов и Регулярные выражения

str match {
case s if s matches "(?i)String1" => 1
case s if s matches "(?i)String2" => 2
case _ => 0
}

Сложный метод:

Имплициты с Интерполяция строк и 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
}

Пример использования примера в REPL:

scala> doStringMatch("StRINg1")
res5: Int = 1

scala> doStringMatch("sTring2")
res8: Int = 2

Ответ 2

Другой подход, который не зависит от регулярных выражений или интерполяторов:

 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!")
  }

Вот еще один способ использования интерполяторов, но не регулярное выражение:

  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!")
  }

Вышеприведенное может также использоваться для сопоставления шаблонов внутри классов case, например:

case class Dog(name: String)

val fido = Dog("FIDO")

fido match {
  case Dog(ci"fido") => "woof"    
  case _ => "meow :("    
}

Ответ 3

Простое решение:

val str = "string1"

str toUpperCase match (str) {
  case "STRING1" => ???
  case "STRING2" => ???
}