Tre*_*vor 9 string parsing scala input
我试图用来readInt()从同一行读取两个整数,但这不是它的工作原理.
val x = readInt()
val y = readInt()
Run Code Online (Sandbox Code Playgroud)
输入1 727我在运行时得到以下异常:
Exception in thread "main" java.lang.NumberFormatException: For input string: "1 727"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:492)
at java.lang.Integer.parseInt(Integer.java:527)
at scala.collection.immutable.StringLike$class.toInt(StringLike.scala:231)
at scala.collection.immutable.StringOps.toInt(StringOps.scala:31)
at scala.Console$.readInt(Console.scala:356)
at scala.Predef$.readInt(Predef.scala:201)
at Main$$anonfun$main$1.apply$mcVI$sp(Main.scala:11)
at scala.collection.immutable.Range.foreach$mVc$sp(Range.scala:75)
at Main$.main(Main.scala:10)
at Main.main(Main.scala)
Run Code Online (Sandbox Code Playgroud)
我通过使用程序工作,readf但对我来说似乎很尴尬和丑陋:
val (x,y) = readf2("{0,number} {1,number}")
val a = x.asInstanceOf[Int]
val b = y.asInstanceOf[Int]
println(function(a,b))
Run Code Online (Sandbox Code Playgroud)
有人建议我只使用Java的Scanner类,(Scanner.nextInt())但是在Scala中有一个很好的惯用方法吗?
编辑:我的解决方案遵循范例的例子:
val Array(a,b) = readLine().split(" ").map(_.toInt)
Run Code Online (Sandbox Code Playgroud)
后续问题:如果字符串中有多种类型,您将如何提取它?(说一个单词,一个int和一个百分比作为Double)
如果你的意思是如何转换val s = "Hello 69 13.5%"成一个(String, Int, Double)最明显的方式
val tokens = s.split(" ")
(tokens(0).toString,
tokens(1).toInt,
tokens(2).init.toDouble / 100)
// (java.lang.String, Int, Double) = (Hello,69,0.135)
Run Code Online (Sandbox Code Playgroud)
或者如上所述,您可以使用正则表达式进行匹配:
val R = """(.*) (\d+) (\d*\.?\d*)%""".r
s match {
case R(str, int, dbl) => (str, int.toInt, dbl.toDouble / 100)
}
Run Code Online (Sandbox Code Playgroud)
如果你实际上并不知道String中将包含哪些数据,那么可能没有太多理由将它从String转换为它所代表的类型,因为你如何使用可能是a的东西String并且可能是在Int?不过,你可以这样做:
val int = """(\d+)""".r
val pct = """(\d*\.?\d*)%""".r
val res = s.split(" ").map {
case int(x) => x.toInt
case pct(x) => x.toDouble / 100
case str => str
} // Array[Any] = Array(Hello, 69, 0.135)
Run Code Online (Sandbox Code Playgroud)
现在要做任何有用的事情,你需要按类型匹配你的值:
res.map {
case x: Int => println("It's an Int!")
case x: Double => println("It's a Double!")
case x: String => println("It's a String!")
case _ => println("It's a Fail!")
}
Run Code Online (Sandbox Code Playgroud)
或者如果你想更进一步,你可以定义一些提取器来为你做转换:
abstract class StringExtractor[A] {
def conversion(s: String): A
def unapply(s: String): Option[A] = try { Some(conversion(s)) }
catch { case _ => None }
}
val intEx = new StringExtractor[Int] {
def conversion(s: String) = s.toInt
}
val pctEx = new StringExtractor[Double] {
val pct = """(\d*\.?\d*)%""".r
def conversion(s: String) = s match { case pct(x) => x.toDouble / 100 }
}
Run Code Online (Sandbox Code Playgroud)
并使用:
"Hello 69 13.5%".split(" ").map {
case intEx(x) => println(x + " is Int: " + x.isInstanceOf[Int])
case pctEx(x) => println(x + " is Double: " + x.isInstanceOf[Double])
case str => println(str)
}
Run Code Online (Sandbox Code Playgroud)
版画
Hello
69 is Int: true
0.135 is Double: true
Run Code Online (Sandbox Code Playgroud)
当然,您可以使分配器匹配您想要的任何东西(货币助记符,名称用'J',URL)并返回您想要的任何类型.如果不是StringExtractor[A]你做的话,你也不仅限于匹配字符串Extractor[A, B].
您可以读取整个行,使用空格拆分它,然后将每个元素(或您想要的那个)转换为整数:
scala> "1 727".split(" ").map( _.toInt )
res1: Array[Int] = Array(1, 727)
Run Code Online (Sandbox Code Playgroud)
对于大多数复杂的输入,您可以查看解析器组合器.
| 归档时间: |
|
| 查看次数: |
5374 次 |
| 最近记录: |