我正在试图找出模式匹配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()
}
}
答案 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
对于从Int
和String
解析的好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
}