1. 程式人生 > 實用技巧 >GoLang字串比較(一)

GoLang字串比較(一)

1. 寫在前面

微信公眾號:[double12gzh]

關注容器技術、關注Kubernetes。問題或建議,請公眾號留言。

在GoLang的使用過程中,我們難免會遇到字串比較的問題。不知道您有沒有總結過,如何做字串比較呢?在本文中我將向在家展示一下,如何進行字串比較
全文將按如下三個方面進行介紹:

  • 字串比較的不同方式
  • 忽略大小的字串比較
  • 不同方法的效能比較

2. 字串比較基本方式

2.1 區分大小寫

相信看到這個題目,您的第一直覺肯定是So easy,也相信您也能很快的寫出如下的程式碼:

package main

import "fmt"

func main() {
    srcString := "This a string"
    destString := "this a string"

    if srcString == destString {
        fmt.Println("Equals")
    } else {
        fmt.Println("Not Equals")
    }
}

2.2 不區分大小寫

2.2.1 使用strings.ToLower

package main

import (
    "fmt"
    "strings"
)

func main() {
    ...

    if strings.ToLower(srcString) == strings.ToLower(destString) {
        fmt.Println("Equals")
    } else {
        fmt.Println("Not Equals")
    }
}

2.2.2 使用strings.Compare

package main

import (
    "fmt"
    "strings"
)

func main() {
    ...
    if strings.Compare(strings.ToLower(srcString), strings.ToLower(destString)) == 0 {
        fmt.Println("Equals")
    } else {
        fmt.Println("Not Equals")
    }
}

這種方法比2.2.1中提到的方式更加優雅和高效,在工作中,如果涉及到不區分大小的字串的比較時,我也經常會採用這樣的方式。

3. 使用EqualFold

這種方式是不區分大小的。這種方法比2.2中提到的方法更高的高效。

package main

import (
    "fmt"
    "strings"
)

func main() {
    ...

    if strings.EqualFold(srcString, destString) == true {
        fmt.Println("Equals")
    } else {
        fmt.Println("Not Equals")
    }
}

4. 效能分析

我們前面只是簡單的給出了結論,哪種方式是比較高效的。那樣是不嚴謹的,那麼,如何來實際測試一下,看一下,到底哪種方式更加的高效呢?
這一章節中,我們將會通過一個測試樣本進行實際測試一下。

4.1 生成資料樣本

在開始之前,我們需要所準備一個數據樣本,樣本的獲取可以通過mockaroo來得到,也可以使用以下程式來生成:

package main

import (
	"crypto/rand"
	"fmt"
	"os"
)

func GenerateRandomString(n int) string {
	const CHARACTER = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
	var bytes = make([]byte, n)

	if _, err := rand.Read(bytes); err != nil {
		panic(err)
	}

	for i, c := range bytes {
		bytes[i] = CHARACTER[c % byte(len(CHARACTER))]
	}

	return string(bytes)
}

func GenFile() {
	f, err := os.Create("mock_data.txt")

	if err != nil {
		panic(err)
	}

	defer f.Close()

	var tempStr string

	for i := 0; i < 200000; i++ {
		tempStr = fmt.Sprintf("%v\n", GenerateRandomString(16))
		if _, err2 := f.WriteString(tempStr); err2 != nil {
			panic(err2)
		}
	}

}

func main() {
	GenFile()
}

我們得到了一個200000行資料的資料樣本:

jeffrey@hacker ~/Desktop/hello
$ cat mock_data.txt | wc -l
200000

4.2 測試讀取耗時

為了測試讀取檔案的耗時,我們寫了以下程式:

main.go

package main

import "main/utils/reader"

func main() {
	//gen.GenFile()
	reader.ReadFile("mock_data.txt")
}

reader.go

package reader

import (
	"bufio"
	"fmt"
	"os"
)

func ReadFile(fileName string) {
	f, err := os.Open(fileName)

	if err != nil {
		panic(err)
	}

	scan := bufio.NewScanner(f)
	scan.Split(bufio.ScanLines)

	for scan.Scan() {
		cmptString := scan.Text()
		fmt.Printf("%s\n", cmptString)
	}

	f.Close()
}

執行上面獲取檔案的程式碼,耗時如下:

...
IBg0Fg79uIwwX9aF
ZcLmE0v1eUqjb6yK
EH6ykTgMTiUBtg3c
aVPont9anIcYBxcW
nKj04D2QIwx1J3VA
bwDRBkuRuw6XDn2I
79rIt3yb8zp5EMRw

real    0m1.122s
user    0m0.000s
sys     0m0.015s

jeffrey@hacker ~/Desktop/hello

4.3 區分大小寫時的耗時

4.3.1 採用==時的耗時

這裡測試直接使用==來判斷字串是否相等時的耗時:

func BasicCompare(src, dest string) bool {
    if srcString == destString {
        return true
    } else {
        return false
    }
}

main.go

package main

import "main/utils/reader"

func main() {
	//gen.GenFile()
	reader.ReadFile("mock_data.txt")
}

reader.go

package reader

import (
	"bufio"
	"fmt"
	"os"
)

func ReadFile(fileName string) {
    srcString := "fuckSBWu"

	f, err := os.Open(fileName)

	if err != nil {
		panic(err)
	}

	scan := bufio.NewScanner(f)
	scan.Split(bufio.ScanLines)

	for scan.Scan() {
		if BasicCompare(scan.Text(), strcString) {
            fmt.Println("Equal")
        }
	}

	f.Close()
}

看一下執行時間:

jeffrey@hacker ~/Desktop/hello
$ time go run main.go

real    0m0.436s
user    0m0.000s
sys     0m0.015s

4.3.2 使用Compare時的耗時

func CompareCompare(src, dest string) bool {
	if strings.Compare(src, dest) == 0 {
		return true
	}
	return false
}
jeffrey@hacker ~/Desktop/hello
$ time go run main.go

real    0m0.395s
user    0m0.000s
sys     0m0.015s

4.3.3 結論

strings.Compare()略顯快一些。

4.4 不區分大小寫時的耗時

4.4.1 使用==時的耗時

func CaseInSensitiveBasicCompare(src, dest string) bool {
	if strings.ToLower(src) == strings.ToLower(dest) {
		return true
	} else {
		return false
	}
}
jeffrey@hacker ~/Desktop/hello
$ time go run main.go

real    0m0.423s
user    0m0.000s
sys     0m0.015s

4.4.2 使用Compare時的耗時

func CaseInSensitiveCompareCompare(src, dest string) bool {
	if strings.Compare(strings.ToLower(src), strings.ToLower(dest)) == 0 {
		return true
	} else {
		return false
	}
}
jeffrey@hacker ~/Desktop/hello
$ time go run main.go

real    0m0.426s
user    0m0.015s
sys     0m0.000s

4.4.3 使用EqualFold時的耗時

jeffrey@hacker ~/Desktop/hello
$ time go run main.go

real    0m0.394s
user    0m0.015s
sys     0m0.000s

5. 總結

EqualFold是最快的一種字串比較的方式。本文測試方式並不是很地道,不是非常的嚴謹,關於如何更加準確的測試,我將在明天的文章中跟大家一起分享一下。