golang split需要注意的一个点

str := "1,2,3,4" //case 1
arr := strings.Split(str, ",")
fmt.Printf("%q\n", arr)
fmt.Println(len(arr))
str = "" //case 2
arr = strings.Split(str, ",")
fmt.Printf("%q\n", arr)
fmt.Println(len(arr))

// output
["1" "2" "3" "4"]
4
[""]
1

在case1的情况,没什么问题;在case2的情况下,len(arr) 的值是 1

原因:

Split(s,sep string) 方法底层调用下面的方法genSplit(),其中n=-1<0意思是把待查字符串中所有的分段都返回

func genSplit(s, sep string, sepSave, n int) []string {
	if n == 0 {
		return nil
	}
	if sep == "" {
		return explode(s, n)
	}
	if n < 0 {
		n = Count(s, sep) + 1
	}

	a := make([]string, n)
	n--
	i := 0
	for i < n {
		m := Index(s, sep)
		if m < 0 {
			break
		}
		a[i] = s[:m+sepSave]
		s = s[m+len(sep):]
		i++
	}
	a[i] = s
	return a[:i+1]
}

n = Count(s, sep) + 1,其中的Count()方法如下,也是调用的底层的internal/bytealg包里的CountString(s string,sep byte) int方法

func Count(s, substr string) int {
	// special case
	if len(substr) == 0 {
		return utf8.RuneCountInString(s) + 1
	}
	if len(substr) == 1 {
		return bytealg.CountString(s, substr[0])
	}
	n := 0
	for {
		i := Index(s, substr)
		if i == -1 {
			return n
		}
		n++
		s = s[i+len(substr):]
	}
}

CountString()的方法如下:

func countGenericString(s string, c byte) int {
    n := 0
    for i := 0; i < len(s); i++ {
        if s[i] == c {
            n++
        }
    }
    return n
}

为什么空字符串会返回长度为1的空字符串数组——[""],就是因为countGenericString("",",")返回了0,这个0在genSplit()里第9行与1相加,在第12行处创建了一个长度为1的字符串数组。

它这么做也不是因为啥,只是说我给你一个字符串a,按某个字符串b进行分割,如果没有能分割的,那就返回a,返回原始的数据。

Split()方法原理,遍历了两次字符串,第一轮的作用在于创建长度为n的slice,为第二轮来存放最后的结果。空间换时间。空间O(n),时间O(n)。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值