给浮点数字符串加逗号
要求:
不用递归,支持浮点数处理和一个可选的正负号处理
代码:
package gopl
// Comma 非递归版,给数字字符串每3位加","且处理开头的-、符号
func Comma(s string) string {
if len(s) <= 3 {
return s
}
// 获取字符串头部非数字部分
head := ""
i := 0
for _, j := range []byte(s) {
if j >= 48 && j <= 57 {
break
}
i++
}
if len(s[i:]) <= 3 {
return s
}
head = s[:i]
s = s[i:]
// 获取字符串小数点及后面部分
tail := ""
for i, j := range []byte(s) {
if j == 46 {
tail = s[i:]
s = s[:i]
break
}
}
var b bytes.Buffer
b.WriteString(head)
l := len(s)
for {
if l > 3 {
m := l % 3
if m == 0 {
m = 3
}
b.WriteString(s[:m])
b.WriteString(",")
s = s[m:]
l -= m
} else {
b.WriteString(s)
break
}
}
b.WriteString(tail)
return b.String()
}
测试:
func TestComm(t *testing.T) {
gots := []string{
"12", "123", "1234", "12345", "123456", "1234567", "12345678",
"-12.1234", "-123.1234", "-1234.1234", "+12345.1234", "-123456.1234", "-1234567.1234", "-12345678.1234",
"abc12.1234", "abc123.1234", "abc1234.1234", "abc12345.1234", "abc123456.1234", "abc1234567.1234", "abc12345678.1234",
}
wants := []string{
"12", "123", "1,234", "12,345", "123,456", "1,234,567", "12,345,678",
"-12.1234", "-123.1234", "-1,234.1234", "+12,345.1234", "-123,456.1234", "-1,234,567.1234", "-12,345,678.1234",
"abc12.1234", "abc123.1234", "abc1,234.1234", "abc12,345.1234", "abc123,456.1234", "abc1,234,567.1234", "abc12,345,678.1234",
}
ln := len(gots)
for i := 0; i < ln; i++ {
got := Comma(gots[i])
want := wants[i]
if !reflect.DeepEqual(got, want) {
t.Errorf("Get: \"%v\" ;Want: \"%v\"", got, want)
}
}
}
小结:
关于字符串拼接有3种常用手段,场景各不相同:
1.少量字符串拼接使用+;
2.拼接多个已存在的子串用c := strings.Join([]string{a,b},",");
3.子串动态生成时用bytes.Buffer。
bytes.Buffer提供可扩容的字节缓冲区,实质是对切片的封装;结构中包含一个64字节的小切片,避免小内存分配,在buff空间不足时会自动扩容。在循环中拼接字符串强烈建议使用bytes.Buffer,它可以避免用+拼接字符串时每次循环都得申请一次内存,运行效率比用+高出很多!
判断2个乱序字符串是否相同
要求:
编写一个函数,判断两个字符串是否是相互打乱的,也就是说它们有着相同的字符,但是对应不同的顺序。
代码:
package gopl
func Compare(a, b string) bool {
count := func (s string) (m map[int32]int) {
m = make(map[int32]int)
for _, i := range s {
m[i]++
}
return
}
if len(a) != len(b) {
return false
}
aMap := count(a)
bMap := count(b)
for k, v := range aMap {
if bMap[k] != v {
return false
}
}
return true
}
测试:
func TestCompare(t *testing.T){
gots1 := []string{
"-12.1234", "-123.1234", "-1234.1234", "-12345.1234", "-123456.1234", "-1234567.1234", "-12345678.1234",
"abc12.1234", "abc123.1234", "abc1234.1234", "abc12345.1234", "abc123456.1234", "abc1234567.1234", "abc12345678.1234",
}
gots2 := []string{
"1234-12.", "123-123.4", "-1234.1234", "-112342345.", "-56.11234234", "-12367.123445", "-12673458.1234",
"abc12.1234", "a2341bc.123", "a234.12bc134", "abc45.1212334", "abc123456.1234", "ab234567c1.1234", "ac1234b5678.1234",
}
ln := len(gots1)
for i := 0; i < ln; i++ {
got := Compare(gots1[i],gots2[i])
if !reflect.DeepEqual(got, true) {
t.Errorf("Source: \"%v\" ;Target: \"%v\" ;Compare !=\"%v\"", gots1[i],gots2[i], true)
}
}
}
小结:
1.Go语言支持函数嵌套,方式是将匿名函数传值给变量名。
2.Go语言的Map是乱序的,要比较2个Map是否相等只能通过循环遍历的方式。