Scala中如何提取字符串里的带小数数字?解决replaceAll提取异常
Scala中提取带小数数字的正确方法(解决
1.8 min提取异常问题) 嘿,我来帮你搞定这两个字符串提取数字的问题!之前处理类似需求时也踩过replaceAll("\\D+","")的坑,刚好能给你分享实用的解决方案。
问题1:如何在Scala中从字符串提取带小数的数字?
核心思路是用正则表达式匹配符合小数格式的字符序列,而不是简单替换非数字字符。因为直接替换非数字会把小数点(.)也删掉,这就是你第二个问题的根源。
常用的正则模式有两种,根据你的需求选择:
\d+\.?\d*:匹配以数字开头的整数或小数(比如1.8、123),不匹配.5这种开头是小数点的情况\d*\.?\d+:匹配所有整数和小数(包括.5、1.8、123)
在Scala中可以这样实现:
// 定义正则模式 val decimalPattern = """\d+\.?\d*""".r // 示例字符串 val sampleStr1 = "The price is 29.99 dollars" val sampleStr2 = "Duration: .5 hours" // 提取第一个匹配的数字 val num1 = decimalPattern.findFirstIn(sampleStr1).getOrElse("No match") val num2 = """\d*\.?\d+""".r.findFirstIn(sampleStr2).getOrElse("No match") println(num1) // 输出: 29.99 println(num2) // 输出: .5
如果要提取字符串中所有带小数的数字,用findAllIn方法即可:
val strWithMultipleNums = "Values: 1.2, 3, 4.56, .7" val allNums = """\d*\.?\d+""".r.findAllIn(strWithMultipleNums).toList // allNums 结果: List("1.2", "3", "4.56", ".7")
问题2:解决1.8 min提取得到18的异常
你用replaceAll("\\D+","")得到18的原因很简单:\D匹配所有非数字字符,而小数点.属于非数字,所以被一起替换掉了,自然就丢失了小数部分。
这里给你两种快速解决的方案:
方案1:精准匹配小数(推荐)
直接用上面提到的正则匹配方法,针对1.8 min的场景:
val targetStr = "1.8 min" val result = """\d+\.?\d*""".r.findFirstIn(targetStr).getOrElse("") println(result) // 输出: 1.8
这种方法最可靠,只会提取符合小数格式的内容,不会引入多余字符。
方案2:替换时保留小数点
如果你更倾向于用替换的方式,可以修改正则,只替换掉除了数字和小数点之外的字符:
val targetStr = "1.8 min" val result = targetStr.replaceAll("[^\\d.]", "") println(result) // 输出: 1.8
⚠️ 注意:如果字符串里有多个小数点(比如"1.8.3 min"),这种方法会得到"1.8.3",这时候需要额外处理多余的小数点:
val strWithMultipleDots = "1.8.3 min" val cleaned = strWithMultipleDots.replaceAll("[^\\d.]", "") // 处理多个小数点,只保留第一个,后面的小数点转为数字 val validDecimal = if (cleaned.count(_ == '.') > 1) { val parts = cleaned.split("\\.") parts.head + "." + parts.tail.mkString } else cleaned println(validDecimal) // 输出: 1.83
内容的提问来源于stack exchange,提问作者supernatural
相关产品推荐
相关产品推荐

