110
extractx/number.go
Normal file
110
extractx/number.go
Normal file
@@ -0,0 +1,110 @@
|
||||
package extractx
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var rxNumber = regexp.MustCompile(`\-?\d+[\d.,]*\d*`)
|
||||
|
||||
// 提取的内容默认为 1,234.56 格式的数字,未实现根据国家标准实现提取
|
||||
// https://zhuanlan.zhihu.com/p/157980325
|
||||
func clean(s string) string {
|
||||
s = strings.TrimSpace(s)
|
||||
if s == "" {
|
||||
return s
|
||||
}
|
||||
s = strings.ReplaceAll(s, ",", "")
|
||||
n := len(s)
|
||||
if s[n-1:] == "." {
|
||||
s = s[n-2 : n-1]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func Number(s string) string {
|
||||
if s == "" {
|
||||
return ""
|
||||
}
|
||||
return clean(rxNumber.FindString(s))
|
||||
}
|
||||
|
||||
func Numbers(s string) []string {
|
||||
if s == "" {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
matches := rxNumber.FindAllString(s, -1)
|
||||
if matches == nil {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
for i, v := range matches {
|
||||
matches[i] = clean(v)
|
||||
}
|
||||
return matches
|
||||
}
|
||||
|
||||
func Float64(s string) float64 {
|
||||
if s = Number(s); s != "" {
|
||||
if v, err := strconv.ParseFloat(s, 64); err == nil {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func Float32(s string) float32 {
|
||||
if s = Number(s); s != "" {
|
||||
if v, err := strconv.ParseFloat(s, 64); err == nil {
|
||||
return float32(v)
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func Int64(s string) int64 {
|
||||
if s = Number(s); s != "" {
|
||||
if v, err := strconv.ParseInt(s, 10, 64); err == nil {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func Int32(s string) int32 {
|
||||
if s = Number(s); s != "" {
|
||||
if v, err := strconv.ParseInt(s, 10, 32); err == nil {
|
||||
return int32(v)
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func Int16(s string) int16 {
|
||||
if s = Number(s); s != "" {
|
||||
if v, err := strconv.ParseInt(s, 10, 16); err == nil {
|
||||
return int16(v)
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func Int8(s string) int8 {
|
||||
if s = Number(s); s != "" {
|
||||
if v, err := strconv.ParseInt(s, 10, 16); err == nil {
|
||||
return int8(v)
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func Int(s string) int {
|
||||
if s = Number(s); s != "" {
|
||||
if v, err := strconv.ParseInt(s, 10, 16); err == nil {
|
||||
return int(v)
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
59
extractx/number_test.go
Normal file
59
extractx/number_test.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package extractx
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNumber(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tag string
|
||||
string string
|
||||
expected string
|
||||
}{
|
||||
{"t1", "123", "123"},
|
||||
{"t2", "12.3", "12.3"},
|
||||
{"t3", "1,234.3", "1234.3"},
|
||||
{"t4", " ab 1 123", "1"},
|
||||
{"t5", ".", ""},
|
||||
{"t6", ",", ""},
|
||||
{"t7", ".,", ""},
|
||||
{"t8", "100 23.", "100"},
|
||||
{"t8.1", "$100 $23.", "100"},
|
||||
{"t9", "-1", "-1"},
|
||||
{"t10", "-1-1", "-1"}, // todo maybe is empty
|
||||
{"t11", "+1", "1"},
|
||||
{"t12", "+1+1", "1"}, // todo maybe is empty
|
||||
{"t13", "1.0 out of 5 stars", "1.0"},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
n := Number(testCase.string)
|
||||
assert.Equal(t, testCase.expected, n, testCase.tag)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNumbers(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tag string
|
||||
string string
|
||||
expected []string
|
||||
}{
|
||||
{"t1", "123", []string{"123"}},
|
||||
{"t2", "12.3", []string{"12.3"}},
|
||||
{"t3", "1,234.3", []string{"1234.3"}},
|
||||
{"t4", " ab 1 123", []string{"1", "123"}},
|
||||
{"t5", " ab .1 123", []string{"1", "123"}},
|
||||
{"t5", " ab ,1 123", []string{"1", "123"}},
|
||||
{"t6", " ab 1. 123", []string{"1", "123"}},
|
||||
{"t7", "$100,$200", []string{"100", "200"}},
|
||||
{"t8", "1,2.3,4", []string{"12.34"}},
|
||||
{"t9", "1, 2.3, 4", []string{"1", "2.3", "4"}},
|
||||
{"t10", "-123,4", []string{"-1234"}},
|
||||
{"t11", "1-1", []string{"1", "-1"}}, // todo May be return empty string
|
||||
{"t12", "N1-1", []string{"1", "-1"}}, // todo May be return empty string
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
n := Numbers(testCase.string)
|
||||
assert.Equal(t, testCase.expected, n, testCase.tag)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user