如何优化Go语言中数值与单位的拆分逻辑
不使用正则表达式拆分带单位的浮点数值
我有一组字符串值,示例如下:
values := [5]string{"32.5ms", "32.5 ms", "32.5%", "32.5 %", "none"}
注意这些值里,数值和计量单位(比如ms、%)之间可能有空格,也可能没有,甚至可能有多个空格。我需要把每个有效值拆分成浮点数字符串和计量单位两部分。
目前我用正则表达式实现了需求,代码如下:
package main import ( "fmt" "regexp" "strings" ) func main() { regexFloatNumbers := regexp.MustCompile(`[-]?\d[\d,]*[\.]?[\d{2}]*`) values := [5]string{"32.5ms", "32.5 ms", "32.5%", "32.5 %", "none"} for _, value := range values { if regexFloatNumbers.MatchString(value) { floatValue := regexFloatNumbers.FindString(value) fmt.Printf("ORIGINAL VALUE: %q\n", value) fmt.Printf("UNIT: %q\n", strings.TrimSpace(regexFloatNumbers.Split(value, -1)[1])) fmt.Printf("FLOAT VALUE: %v\n\n", floatValue) } else { fmt.Printf("float value for %v has not being found!", value) } } }
现在想知道有没有更简洁的实现方式,比如不用正则表达式?
无正则的实现方案
方案一:遍历字符确定拆分点
通过遍历字符串的每个字符,找到第一个不属于数值组成部分(数字、负号、小数点)的位置,以此拆分数值和单位。这种方法逻辑直观,适合自定义规则。
package main import ( "fmt" "strings" "unicode" ) func splitValue(s string) (floatStr, unit string, ok bool) { if s == "" { return "", "", false } // 定位数值部分的结束位置 splitIdx := 0 for i, r := range s { if unicode.IsDigit(r) || r == '.' || r == '-' { splitIdx = i + 1 } else { break } } // 处理无效数值情况(比如单独的-或.) if splitIdx == 0 || (splitIdx == len(s) && (s == "-" || s == ".")) { return "", "", false } floatStr = s[:splitIdx] unit = strings.TrimSpace(s[splitIdx:]) // 可选:如果需要严格验证浮点数格式,可在此处调用strconv.ParseFloat检查floatStr return floatStr, unit, true } func main() { values := [5]string{"32.5ms", "32.5 ms", "32.5%", "32.5 %", "none"} for _, v := range values { floatStr, unit, ok := splitValue(v) if ok { fmt.Printf("ORIGINAL VALUE: %q\n", v) fmt.Printf("UNIT: %q\n", unit) fmt.Printf("FLOAT VALUE: %v\n\n", floatStr) } else { fmt.Printf("float value for %v has not been found!\n", v) } } }
方案二:借助标准库解析确定长度
利用strconv.ParseFloat的返回值,它会返回成功解析的字符数,以此精准定位数值部分的长度,同时自带数值有效性验证,逻辑更简洁可靠。
package main import ( "fmt" "strconv" "strings" ) func splitValue(s string) (floatStr, unit string, ok bool) { s = strings.TrimSpace(s) if s == "" { return "", "", false } // 解析浮点数,获取成功解析的字符数 _, parsedLen, err := strconv.ParseFloat(s, 64) if err != nil { return "", "", false } floatStr = s[:parsedLen] unit = strings.TrimSpace(s[parsedLen:]) return floatStr, unit, true } func main() { values := [5]string{"32.5ms", "32.5 ms", "32.5%", "32.5 %", "none"} for _, v := range values { floatStr, unit, ok := splitValue(v) if ok { fmt.Printf("ORIGINAL VALUE: %q\n", v) fmt.Printf("UNIT: %q\n", unit) fmt.Printf("FLOAT VALUE: %v\n\n", floatStr) } else { fmt.Printf("float value for %v has not been found!\n", v) } } }
内容的提问来源于stack exchange,提问作者Possenti
相关产品推荐
相关产品推荐

