大小写匹配基于算法的字符串。我应该使用哪种算法?

时间:2017-02-22 18:06:17

标签: algorithm scala pattern-matching string-matching

我需要在我的代码中将电视收视率(用于电视节目)转换为该评级的案例对象。因此,我有一个像这样的案例匹配:

def fromString(s: String): Option[TvRating] = s.toLowerCase match {
  case "tvy" | "tv-y" | "tv y" | "y" => Some(tvY)
  case "tvg" | "tv-g" | "tv g" | "g" => Some(tvG)
  case "tvpg" | "tv-pg" | "tv pg" | "pg" => Some(tvG)
  case "tv14" | "tv-14" | "tv 14" | "14" => Some(tv14)
  case "tvma" | "tv-ma" | "tv ma" | "ma" => Some(tvMA)
  case _ => Some(noTvRating)
}

正如你所看到的那样,我试图匹配每个评级的所有排列,这很麻烦,但仍然没有考虑像“tv.14”或“成熟观众”这样的事情。

是否有像soundX这样的算法,但对于像这些评级这样的代码我可以作为最后的手段使用。然后我的代码将如下所示:

def fromString(s: String): Option[TvRating] = s.toLowerCase match {
  case "tvy" | "tv-y" | fancyAlgo(s, "tv-y") => Some(tvY)
  case "tvg" | "tv-g" | fancyAlgo(s, "tv-g") => Some(tvG)
  case "tvpg" | "tv-pg" | fancyAlgo(s, "tv-pg") => Some(tvG)
  case "tv14" | "tv-14" | fancyAlgo(s, "tv-14") => Some(tv14)
  case "tvma" | "tv-ma" | fancyAlgo(s, "tv-ma") => Some(tvMA)
  case _ => Some(noTvRating)
}

或者我可以使这些匹配更健壮的任何其他建议。由于tv-g不是像“狗”或“马”这样的词,我不能基于音频或类似的发声词。

这是评级的一个例子。还有其他比赛。这是星级评分的另一个例子(如烂番茄的电影评级)

def fromString(s: String): Option[StarRating] = s.toLowerCase match {
  case "1" | "one star" | "one stars" => Some(oneStar)
  case "1.5" | "1.5 stars" | "one and a half stars" => Some(oneAndHalfStar)
  case "2" | "2 stars" | "two stars" => Some(twoStars)
  case "2.5" | "2.5 stars" | "two and a half stars" => Some(twoAndHalfStars)
  case "3" | "3 stars" | "three stars" => Some(threeStars)
  case "3.5" | "3.5 stars" | "three and a half stars" => Some(threeAndHalfStars)
  case "4" | "4 stars" | "four stars" => Some(fourStars)
  case _ => Some(noStars)
}

干杯!

2 个答案:

答案 0 :(得分:2)

开始数据驱动:

val ratings = scala.collection.mutable.Map[String, String]() withDefaultValue "noTVRating"

type TvRating = String

def addRatingStyle(base:String, result:String) = {
  val suffix = base.stripPrefix("tv")
  ratings += ("tv"+suffix->result)
  ratings += ("tv-"+suffix->result)
  ratings += ("tv "+suffix->result)
  ratings += (suffix->result)
}

addRatingStyle("tvy", "tvy")
addRatingStyle("tvg", "tvg")
addRatingStyle("tvpg", "tvpg")
addRatingStyle("tv14", "tv14")
addRatingStyle("tvma", "tvma")


def fromString(s: String): Option[TvRating] = Some(ratings(s.toLowerCase)) 

答案 1 :(得分:2)

使用case objectunapply方式定义您的个人评分。一个简单的正则表达式可能会处理剩下的事情:

sealed trait TVRating

case object Youth extends TVRating {
  def unapply(s: String): Option[TVRating] = {
    //insert fancier match logic here...
    if( s.matches("tv.*y") || s.equals("y")) {
      Some(Youth)
    } else {
      None
    }
  }
}

case object General extends TVRating {
  def unapply(s: String): Option[TVRating] = {
    //insert fancier match logic here...
    if( s.matches("tv.*g")) {
      Some(Youth)
    } else {
      None
    }
  }
}

object Main extends App {

  override def main(args: Array[String]) = {
    "tv.y" match {
        case Youth(s) => println("Youth")
        case General(s) => println("General")
        case _ => println("Unknown")
    }
  }
}