最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang?統(tǒng)計(jì)字符串中數(shù)字字母數(shù)量的實(shí)現(xiàn)方法

 更新時(shí)間:2022年06月01日 11:01:06   作者:戀喵大鯉魚  
這篇文章主要介紹了Golang?統(tǒng)計(jì)字符串中數(shù)字字母數(shù)量,本文給出了兩種從字符串獲取數(shù)字與字母數(shù)量的方法,分別是ASCII 碼值和正則表達(dá)式,需要的朋友可以參考下

1.需求說(shuō)明

記錄一下項(xiàng)目對(duì)用戶 UGC 文本進(jìn)行字?jǐn)?shù)限制的具體實(shí)現(xiàn)。

不同的產(chǎn)品,出于種種原因,一般都會(huì)對(duì)用戶輸入的文本內(nèi)容做字?jǐn)?shù)限制。

  • 出于產(chǎn)品定位,比如 140 字符限制的 Twitter,讓內(nèi)容保持簡(jiǎn)潔凝練,易于閱讀;
  • 出于用戶的閱讀體驗(yàn),過(guò)多的文字會(huì)造成閱讀疲勞,合適的字?jǐn)?shù)能夠提高閱讀舒適度;
  • 出于技術(shù)與成本的考慮,不設(shè)上限的 UGC 內(nèi)容會(huì)引發(fā)一些潛在的問(wèn)題,比如增加存儲(chǔ)的成本,降低檢索效率等。

回到自己的項(xiàng)目,是一個(gè)用戶發(fā)帖的業(yè)務(wù)場(chǎng)景。產(chǎn)品同學(xué)給到的要求是:

  • 帖子名稱,限制在 25 個(gè)字;
  • 帖子正文,限制在 1500 字;
  • 關(guān)于字的說(shuō)明:1 個(gè)漢字為一個(gè)字,一個(gè) Emoji 表情相當(dāng)于 1 個(gè)字,2 個(gè)數(shù)字/英文字母相當(dāng)于 1 個(gè)字。

正常情況下,漢字,Emoji 字符,數(shù)字與英文字母都是單獨(dú)的字符。這里 2 個(gè)數(shù)字/英文算作 1 個(gè)字,所以在計(jì)算字符串長(zhǎng)度時(shí),不能夠使用 []rune 強(qiáng)轉(zhuǎn)后來(lái)獲取其長(zhǎng)度,而是需要統(tǒng)計(jì)出數(shù)字與英文字母的數(shù)量,再加上其他字符數(shù)量,作為其長(zhǎng)度。所以,要想實(shí)現(xiàn)產(chǎn)品同學(xué)的要求,關(guān)鍵是需要統(tǒng)計(jì)出用戶輸入文本中的數(shù)字與英文字母的數(shù)量。

2.實(shí)現(xiàn)

在 Golang,一般有兩種方法。

2.1 ASCII 碼值法

數(shù)字和英文字母的 ASCII 碼值我們是知道的,通過(guò)對(duì)原字符串遍歷,便可統(tǒng)計(jì)出數(shù)字/英文字母的數(shù)量。

// GetAlphanumericNumByASCII 根據(jù) ASCII 碼值獲取字母數(shù)字?jǐn)?shù)量。
func GetAlphanumericNumByASCII(s string) int {
	num := int(0)
	for i := 0; i < len(s); i++ {
		switch {
		case 48 <= s[i] && s[i] <= 57: // 數(shù)字
			fallthrough
		case 65 <= s[i] && s[i] <= 90: // 大寫字母
			fallthrough
		case 97 <= s[i] && s[i] <= 122: // 小寫字母
			num++
		default:
		}
	}
	return num
}

// 或者
// GetAlphanumericNumByASCIIV2 根據(jù) ASCII 碼值獲取字母數(shù)字?jǐn)?shù)量。
func GetAlphanumericNumByASCIIV2(s string) int {
	num := int(0)
	for _, c := range s {
		switch {
		case '0' <= c && c <= '9':
			fallthrough
		case 'a' <= c && c <= 'z':
			fallthrough
		case 'A' <= c && c <= 'Z':
			num++
		default:
		}
	}
	return num
}

2.2 正則表達(dá)式

我們可以利用 Golang 標(biāo)準(zhǔn)庫(kù)包 regexp 獲取指定表達(dá)式的字串?dāng)?shù)量。

// GetAlphanumericNumByRegExp 根據(jù)正則表達(dá)式獲取字母數(shù)字?jǐn)?shù)量。
func GetAlphanumericNumByRegExp(s string) int {
	rNum := regexp.MustCompile(`\d`)
	rLetter := regexp.MustCompile("[a-zA-Z]")
	return len(rNum.FindAllString(s, -1)) + len(rLetter.FindAllString(s, -1))
}

我們可以寫個(gè)單測(cè)來(lái)驗(yàn)證下上面三個(gè)函數(shù)的正確性。

package string
import "testing"
func TestGetAlphanumericNumByASCII(t *testing.T) {
	type args struct {
		s string
	}
	tests := []struct {
		name string
		args args
		want int
	}{
		{
			name: "包含數(shù)字",
			args: args{"108條梁山好漢"},
			want: 3,
		},
		{
			name: "包含字母",
			args: args{"一百條梁山man"},
			want: 3,
		},
		{
			name: "包含數(shù)字與字母",
			args: args{"108條梁山man"},
			want: 6,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := GetAlphanumericNumByASCII(tt.args.s); got != tt.want {
				t.Errorf("GetAlphanumericNumByASCII() = %v, want %v", got, tt.want)
			}
		})
	}
}
func TestGetAlphanumericNumByASCIIV2(t *testing.T) {
	type args struct {
		s string
	}
	tests := []struct {
		name string
		args args
		want int
	}{
		{
			name: "包含數(shù)字",
			args: args{"108條梁山好漢"},
			want: 3,
		},
		{
			name: "包含字母",
			args: args{"一百條梁山man"},
			want: 3,
		},
		{
			name: "包含數(shù)字與字母",
			args: args{"108條梁山man"},
			want: 6,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := GetAlphanumericNumByASCIIV2(tt.args.s); got != tt.want {
				t.Errorf("GetAlphanumericNumByASCII() = %v, want %v", got, tt.want)
			}
		})
	}
}
func TestGetAlphanumericNumByRegExp(t *testing.T) {
	type args struct {
		s string
	}
	tests := []struct {
		name string
		args args
		want int
	}{
		{
			name: "包含數(shù)字",
			args: args{"108條梁山好漢"},
			want: 3,
		},
		{
			name: "包含字母",
			args: args{"一百條梁山man"},
			want: 3,
		},
		{
			name: "包含數(shù)字與字母",
			args: args{"108條梁山man"},
			want: 6,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := GetAlphanumericNumByRegExp(tt.args.s); got != tt.want {
				t.Errorf("GetAlphanumericNumByRegExp() = %v, want %v", got, tt.want)
			}
		})
	}
}

運(yùn)行go test main/string命令,其中 main/string 為單元測(cè)試所在包的路徑。輸出如下:

ok      main/string     0.355s

驗(yàn)證無(wú)誤。

3.性能對(duì)比

上面提到的兩種方法都可以用來(lái)獲取字符串中數(shù)字與英文字母的數(shù)量,那么我們應(yīng)該采用哪一種方法呢?

功能上沒(méi)有差別,那么我們來(lái)看下性能對(duì)比吧。

func BenchmarkGetAlphanumericNumByASCII(b *testing.B) {
	for n := 0; n < b.N; n++ {
		GetAlphanumericNumByASCII("108條梁山man")
	}
}
func BenchmarkGetAlphanumericNumByASCIIV2(b *testing.B) {
	for n := 0; n < b.N; n++ {
		GetAlphanumericNumByASCIIV2("108條梁山man")
	}
}
func BenchmarkGetAlphanumericNumByRegExp(b *testing.B) {
	for n := 0; n < b.N; n++ {
		GetAlphanumericNumByRegExp("108條梁山man")
	}
}

運(yùn)行上面的基準(zhǔn)測(cè)試,輸出如下:

go test -bench=. -benchmem main/string

goos: windows
goarch: amd64
pkg: main/string
cpu: Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz
BenchmarkGetAlphanumericNumByASCII-8            89540210                12.67 ns/op            0 B/op          0 allocs/op
BenchmarkGetAlphanumericNumByASCIIV2-8          63227778                19.11 ns/op            0 B/op          0 allocs/op
BenchmarkGetAlphanumericNumByRegExp-8             465954              2430 ns/op            1907 B/op         27 allocs/op
PASS
ok      main/string     3.965s

不測(cè)不知道,一測(cè)嚇一跳。通過(guò)正則表達(dá)式的實(shí)現(xiàn)方式,代碼雖然簡(jiǎn)潔,但是涉及多次內(nèi)存配分,性能與 ASCII 碼值法相比,差距非常之大,是 ASCII 碼值法的 200 倍左右。所以從性能的考慮,推薦使用 ASCII 碼值的方式獲取數(shù)字字母數(shù)量。

ASCII 碼值法有兩種遍歷方式,一種是按照字節(jié)遍歷,一種是按照 rune 字符遍歷。因?yàn)楹笳呱婕?rune 字符的判斷,所以性能會(huì)差一些。推薦使用按照字節(jié)遍歷。

4.小結(jié)

本文給出了兩種從字符串獲取數(shù)字與字母數(shù)量的方法:

  • ASCII 碼值。
  • 正則表達(dá)式。

出于性能的考慮,推薦使用 ASCII 碼值法,并使用字節(jié)遍歷的方式。

此外,本文給出的兩種方法,三種實(shí)現(xiàn)方式,相關(guān)源碼已放置開(kāi)源庫(kù) go-huge-util,可 import 直接使用。

package main
import (
	"fmt"
	huge "github.com/dablelv/go-huge-util"
)
func main() {
	fmt.Println(huge.GetAlphanumericNumByASCII("108條梁山man"))  	// 6
	fmt.Println(huge.GetAlphanumericNumByASCIIV2("108條梁山man"))  	// 6
	fmt.Println(huge.GetAlphanumericNumByRegExp("108條梁山man")) 	// 6
}

參考文獻(xiàn)

golang統(tǒng)計(jì)出其中英文字母、空格、數(shù)字和其它字符的個(gè)數(shù)

到此這篇關(guān)于Golang 統(tǒng)計(jì)字符串中數(shù)字字母數(shù)量的文章就介紹到這了,更多相關(guān)Golang 統(tǒng)計(jì)字符串內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語(yǔ)言中ORM框架GORM使用介紹

    Go語(yǔ)言中ORM框架GORM使用介紹

    GORM是Go語(yǔ)言中最受歡迎的ORM庫(kù)之一,它提供了強(qiáng)大的功能和簡(jiǎn)潔的?API,讓數(shù)據(jù)庫(kù)操作變得更加簡(jiǎn)單和易維護(hù),本文將詳細(xì)介紹GORM的常見(jiàn)用法,包括數(shù)據(jù)庫(kù)連接、模型定義、CRUD、事務(wù)管理等方面,幫助大家快速上手使用GORM進(jìn)行Web后端開(kāi)發(fā)
    2023-06-06
  • 淺談Go Slice 高級(jí)實(shí)踐

    淺談Go Slice 高級(jí)實(shí)踐

    這篇文章主要介紹了淺談Go Slice 高級(jí)實(shí)踐,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • Go語(yǔ)言中的if條件語(yǔ)句使用詳解

    Go語(yǔ)言中的if條件語(yǔ)句使用詳解

    這篇文章主要介紹了Go語(yǔ)言中的if條件語(yǔ)句的使用,包括if...else語(yǔ)句以及相關(guān)嵌套,需要的朋友可以參考下
    2015-10-10
  • 從并發(fā)到并行解析Go語(yǔ)言中的sync.WaitGroup

    從并發(fā)到并行解析Go語(yǔ)言中的sync.WaitGroup

    Go?語(yǔ)言提供了許多工具和機(jī)制來(lái)實(shí)現(xiàn)并發(fā)編程,其中之一就是?sync.WaitGroup。本文就來(lái)深入討論?sync.WaitGroup,探索其工作原理和在實(shí)際應(yīng)用中的使用方法吧
    2023-05-05
  • 詳解Go并發(fā)編程時(shí)如何避免發(fā)生競(jìng)態(tài)條件和數(shù)據(jù)競(jìng)爭(zhēng)

    詳解Go并發(fā)編程時(shí)如何避免發(fā)生競(jìng)態(tài)條件和數(shù)據(jù)競(jìng)爭(zhēng)

    大家都知道,Go是一種支持并發(fā)編程的編程語(yǔ)言,但并發(fā)編程也是比較復(fù)雜和容易出錯(cuò)的。比如本篇分享的問(wèn)題:競(jìng)態(tài)條件和數(shù)據(jù)競(jìng)爭(zhēng)的問(wèn)題
    2023-04-04
  • Go語(yǔ)言實(shí)現(xiàn)配置熱加載的方法分享

    Go語(yǔ)言實(shí)現(xiàn)配置熱加載的方法分享

    web項(xiàng)目,經(jīng)常需要熱啟動(dòng)各種各樣的配置信息,一旦這些服務(wù)發(fā)生變更,我們需要重新啟動(dòng)web server,以使配置生效,實(shí)現(xiàn)配置熱加載,本文為大家整理了幾個(gè)方法實(shí)現(xiàn)這個(gè)需求,需要的可以參考下
    2023-05-05
  • go語(yǔ)言計(jì)算兩個(gè)時(shí)間的時(shí)間差方法

    go語(yǔ)言計(jì)算兩個(gè)時(shí)間的時(shí)間差方法

    這篇文章主要介紹了go語(yǔ)言計(jì)算兩個(gè)時(shí)間的時(shí)間差方法,涉及Python操作時(shí)間的技巧,需要的朋友可以參考下
    2015-03-03
  • go語(yǔ)言的初始化順序,包,變量,init詳解

    go語(yǔ)言的初始化順序,包,變量,init詳解

    這篇文章主要介紹了go語(yǔ)言的初始化順序,包,變量,init詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • go項(xiàng)目中環(huán)境變量的配置

    go項(xiàng)目中環(huán)境變量的配置

    本文主要介紹了go項(xiàng)目中環(huán)境變量的配置,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-07-07
  • Golang無(wú)限緩存channel的設(shè)計(jì)與實(shí)現(xiàn)解析

    Golang無(wú)限緩存channel的設(shè)計(jì)與實(shí)現(xiàn)解析

    這篇文章主要為大家介紹了Golang無(wú)限緩存channel的設(shè)計(jì)與實(shí)現(xiàn)解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07

最新評(píng)論

祁阳县| 红河县| 仙游县| 神池县| 昌黎县| 西城区| 凤凰县| 顺义区| 沂南县| 贵德县| 新泰市| 西和县| 溧水县| 治县。| 白玉县| 中卫市| 丰城市| 乌鲁木齐市| 乐安县| 盈江县| 方正县| 泸溪县| 新郑市| 泰州市| 凤山市| 乐东| 峨边| 武汉市| 泰顺县| 临夏县| 安陆市| 西乌珠穆沁旗| 光泽县| 琼海市| 武宁县| 偃师市| 扬州市| 罗定市| 太谷县| 淮滨县| 富民县|