Упростите Массив Матч Кейс - Скала - PullRequest
2 голосов
/ 29 апреля 2019

Итак, в одном из мест у нас есть это огромное variable match case утверждение.

Содержит почти 150 различных case утверждений

Выглядит ужасно.

Я хочуразбив его на более мелкие функции, я могу сгруппировать совпадения, скажем, в 10 частей, а затем число case операторов снизится до 15. Это нормально.

В настоящее время это выглядит так

massiveCaseVariable match {
  case "one" => 1
  case "two" => 2
  case "three" => 3
  case "four" => 4
  case "five" => 5
  case "six" => 6
}

Но я не хочу делать это так

massiveCaseVariable match {
  case "one" || "two" || "three" => firstCategory(massiveCaseVariable)
  case "four" || "five" || "six" => secondCategory(massiveCaseVariable)
}

def firstCategory(caseVariable: String): Int =
  caseVariable match {
    case "one"   => 1
    case "two"   => 2
    case "three" => 3
  }

def secondCategory(caseVariable: String): Int =
  caseVariable match {
    case "four" => 4
    case "five" => 5
    case "six"  => 6
  }

Это слишком повторяется.Есть ли лучший, более краткий способ сделать это?

Я на Scala 2.11

PS: примеры приведены только для иллюстрации.Я определенно не пытаюсь сопоставить строки с целыми числами

Ответы [ 4 ]

9 голосов
/ 29 апреля 2019

Если вы хотите просто объединить совпадения, вы можете заметить, что это на самом деле частичные функции (потому что сопоставление может не получиться):

val firstCategory: PartialFunction[String, Int] = {
    case "one"   => 1
    case "two"   => 2
    case "three" => 3
  }

val secondCategory: PartialFunction[String, Int] = {
    case "four" => 4
    case "five" => 5
    case "six"  => 6
  }

, которые можно объединить:

val all = firstCategory orElse secondCategory
all("one")

Интересно, что многие коллекции являются частичными функциями, например Map, поэтому:

val firstCategory = Map[String, Int](
    "one"   -> 1,
    "two"   -> 2,
    "three" -> 3
  )

val secondCategory = Map[String, Int](
    "four" -> 4,
    "five" -> 5,
    "six"  -> 6
  )

val all = firstCategory ++ secondCategory
all("one")

в этом примере должно работать так же.

1 голос
/ 29 апреля 2019

Тогда не используйте сопоставление с образцом или, по крайней мере, само по себе.

trait Handler {
def canHandle(variable: String): Boolean
def handle(variable: String): Int
}
class HandlerCategory1 extends Handler {/*...*/}
class HandlerCategory2 extends Handler {/*...*/}
// ...

val variable: String = ???
val handlers = List(new HandlerCategory1(), new HandlerCategory2())

handlers.find(_.canHandle(variable)).map(_.handle(variable))

Вы можете поместить свое условие из сопоставления с образцом в определенные canHandle() методы.

0 голосов
/ 29 апреля 2019

Вы можете попытаться использовать объекты экстрактора, скрывающие некоторую логику в методах unapply.Трудно ответить лучше без вашего реального кода.Можете ли вы поделиться несколькими фактическими case описаниями их "повторяющейся" природы?

https://danielwestheide.com/blog/2012/11/21/the-neophytes-guide-to-scala-part-1-extractors.html

  trait Hierarchy

  class Case1(val s: String) extends Hierarchy

  object Case1 {
    def unapply(arg: Case1): Boolean = arg.s == "one" || arg.s == "two"
  }

  class Case2(val s: String) extends Hierarchy

  object Case2 {
    def unapply(arg: Case2): Boolean = arg.s == "three" || arg.s == "four" || arg.s == "five"
  }

  class Case3(val s: String) extends Hierarchy

  object Case3 {
    def unapply(arg: Case3): Option[String] = if (arg.s == "six" || arg.s == "seven") Some(arg.s) else None
  }

  class Case4(val s: String) extends Hierarchy

  object Case4 {
    // some other logic
    def unapply(arg: Case4): Option[(String, Int)] = if (arg.s == "eight") Some(arg.s, 8) 
                                                     else if (arg.s == "nine") Some(arg.s, 9) 
                                                     else None
  }

  val massiveCaseVariable: Hierarchy = ???

  massiveCaseVariable match {
    case Case1() => ???
    case Case2() => ???
    case Case3(s) => ???
    case Case4(s, n) => ???
  }
0 голосов
/ 29 апреля 2019

Вы можете организовать это следующим образом

  val all = firstCategory() ++ secondCategory()

  all("some").apply()

  def firstCategory() : Map[String, () => ()] = {
    Map(
      "first" -> (() => {}),
      "second" -> (() => {})
    )
  }
  def secondCategory(): Map[String, () => ()] = {
    Map(
      "third" -> (() => {
        print("some code")
      }),
      "forth" -> (() => {
        print("some other code")
      })
    )
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...