如何模式匹配int字符串?

时间:2017-03-23 16:05:32

标签: scala pattern-matching

我正在试图找出模式匹配Scala中int的字符串表示的最佳方法。我真正希望能做的是这样的事情:

"1234" match {
  // Some cases
  case "five" => 5
  case Int(i) => i // Fails
  case _ => throw new RuntimeException()
}

一种方法是使用正则表达式。一个潜在的问题是它不会检测整数是否太大而不适合int。

val ISINT = "^([+-]?\\d+)$".r

"1234" match {
  case "five" => 5
  case ISINT(t) => t.toInt
  case _ => throw new RuntimeException()
}

另一种方法使用toInt函数返回Option(借用this blog post)。这很好,因为它使标准库弄清楚字符串是否包含整数。问题在于它迫使我将逻辑嵌套在我认为它应该是平坦的地方。

def toInt(s: String): Option[Int] = {
  try {
    Some(s.toInt)
  } catch {
    case e: Exception => None
  }
}

"1234" match {
  case "five" => 5
  case t => toInt(t) match {
    case Some(i) => i
    case None => throw new RuntimeException()
  }
}

4 个答案:

答案 0 :(得分:8)

您可以像这样定义一个自定义提取器

object Int { 
  def unapply(s: String): Option[Int] = util.Try(s.toInt).toOption 
}

使用它就像你想要的那样

"1234" match {
  // Some cases
  case "five" => 5
  case Int(i) => i // works :)
  case _ => throw new RuntimeException()
}

答案 1 :(得分:1)

正则表达式的另一个技巧

Character

答案 2 :(得分:1)

我非常喜欢@Jasper-M的简洁方法,但我尽我所能to avoid generating exceptions as a means of control flow - 更不用说显着的性能成本了。有趣的是,@ Jasper-M的方法非常简洁和优雅,隐藏了这些细节。

因此,如果您想尝试基于非异常的方法来获得乐趣:

val matcher = "1234" match {
  case "five" => Some(BigInt(5L))
  case regex(t) => Some(BigInt(t))
  case _ => None
}
val result: Option[Int] = matcher.filter(_.isValidInt).map(_.toInt)

在这种情况下,您会得到一个Option[Int]]Some对于从IntString解析的好None而言是const express = require('express') const app = express() app.get('/', function(req, res) { // remove the port number if it's there const host = req.get('host').split(':')[0] if(host === "a.com") { res.redirect('/a') } else if(host === "b.com") { res.redirect('/b') } else if(host === "c.com") { res.redirect('/c') } else { // redirect somewhere else } }) app.get('/a', function(req, res) { res.send('hello from a') }) app.get('/b', function(req, res) { res.send('hello from b') }) app.get('/c', function(req, res) { res.send('hello from c') }) app.listen(3000, function() { console.log('Listening on 3000') })

我会首先使用@Jasper-M的方法来观看表演。如果您发现任何事情,请考虑基于非例外的方法。

答案 3 :(得分:0)

也许你可以在比赛中使用后卫?

"12312312313123" match {
   case s: String if s.isInt => "int"
   case _ => "no int"
}

implicit class IsInt(i: String){
  def isInt: Boolean = Try(i.toInt).isSuccess
}