91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Golang如何統計字符串中數字字母的數量

發布時間:2022-06-01 13:46:23 來源:億速云 閱讀:168 作者:iii 欄目:開發技術

今天小編給大家分享一下Golang如何統計字符串中數字字母的數量的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

    1.需求說明

    記錄一下項目對用戶 UGC 文本進行字數限制的具體實現。

    不同的產品,出于種種原因,一般都會對用戶輸入的文本內容做字數限制。

    • 出于產品定位,比如 140 字符限制的 Twitter,讓內容保持簡潔凝練,易于閱讀;

    • 出于用戶的閱讀體驗,過多的文字會造成閱讀疲勞,合適的字數能夠提高閱讀舒適度;

    • 出于技術與成本的考慮,不設上限的 UGC 內容會引發一些潛在的問題,比如增加存儲的成本,降低檢索效率等。

    回到自己的項目,是一個用戶發帖的業務場景。產品同學給到的要求是:

    • 帖子名稱,限制在 25 個字;

    • 帖子正文,限制在 1500 字;

    • 關于字的說明:1 個漢字為一個字,一個 Emoji 表情相當于 1 個字,2 個數字/英文字母相當于 1 個字。

    正常情況下,漢字,Emoji 字符,數字與英文字母都是單獨的字符。這里 2 個數字/英文算作 1 個字,所以在計算字符串長度時,不能夠使用 []rune 強轉后來獲取其長度,而是需要統計出數字與英文字母的數量,再加上其他字符數量,作為其長度。所以,要想實現產品同學的要求,關鍵是需要統計出用戶輸入文本中的數字與英文字母的數量。

    2.實現

    在 Golang,一般有兩種方法。

    2.1 ASCII 碼值法

    數字和英文字母的 ASCII 碼值我們是知道的,通過對原字符串遍歷,便可統計出數字/英文字母的數量。

    // GetAlphanumericNumByASCII 根據 ASCII 碼值獲取字母數字數量。
    func GetAlphanumericNumByASCII(s string) int {
    	num := int(0)
    	for i := 0; i < len(s); i++ {
    		switch {
    		case 48 <= s[i] && s[i] <= 57: // 數字
    			fallthrough
    		case 65 <= s[i] && s[i] <= 90: // 大寫字母
    			fallthrough
    		case 97 <= s[i] && s[i] <= 122: // 小寫字母
    			num++
    		default:
    		}
    	}
    	return num
    }
    
    // 或者
    // GetAlphanumericNumByASCIIV2 根據 ASCII 碼值獲取字母數字數量。
    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 正則表達式

    我們可以利用 Golang 標準庫包 regexp 獲取指定表達式的字串數量。

    // GetAlphanumericNumByRegExp 根據正則表達式獲取字母數字數量。
    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))
    }

    我們可以寫個單測來驗證下上面三個函數的正確性。

    package string
    import "testing"
    func TestGetAlphanumericNumByASCII(t *testing.T) {
    	type args struct {
    		s string
    	}
    	tests := []struct {
    		name string
    		args args
    		want int
    	}{
    		{
    			name: "包含數字",
    			args: args{"108條梁山好漢"},
    			want: 3,
    		},
    		{
    			name: "包含字母",
    			args: args{"一百條梁山man"},
    			want: 3,
    		},
    		{
    			name: "包含數字與字母",
    			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: "包含數字",
    			args: args{"108條梁山好漢"},
    			want: 3,
    		},
    		{
    			name: "包含字母",
    			args: args{"一百條梁山man"},
    			want: 3,
    		},
    		{
    			name: "包含數字與字母",
    			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: "包含數字",
    			args: args{"108條梁山好漢"},
    			want: 3,
    		},
    		{
    			name: "包含字母",
    			args: args{"一百條梁山man"},
    			want: 3,
    		},
    		{
    			name: "包含數字與字母",
    			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)
    			}
    		})
    	}
    }

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

    ok      main/string     0.355s

    驗證無誤。

    3.性能對比

    上面提到的兩種方法都可以用來獲取字符串中數字與英文字母的數量,那么我們應該采用哪一種方法呢?

    功能上沒有差別,那么我們來看下性能對比吧。

    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")
    	}
    }

    運行上面的基準測試,輸出如下:

    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

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

    ASCII 碼值法有兩種遍歷方式,一種是按照字節遍歷,一種是按照 rune 字符遍歷。因為后者涉及 rune 字符的判斷,所以性能會差一些。推薦使用按照字節遍歷。

    4.小結

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

    • ASCII 碼值。

    • 正則表達式。

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

    此外,本文給出的兩種方法,三種實現方式,相關源碼已放置開源庫 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
    }

    以上就是“Golang如何統計字符串中數字字母的數量”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    英山县| 漳浦县| 利津县| 沁阳市| 镶黄旗| 建瓯市| 汝城县| 遵义市| 唐海县| 应用必备| 元氏县| 稷山县| 梨树县| 岢岚县| 金沙县| 罗定市| 介休市| 甘谷县| 石狮市| 湾仔区| 英德市| 子洲县| 锦屏县| 大兴区| 嫩江县| 海南省| 皋兰县| 剑河县| 迭部县| 肇东市| 南安市| 长乐市| 枣阳市| 红安县| 灌云县| 海安县| 耿马| 姚安县| 钟山县| 盱眙县| 外汇|