3 回答

TA貢獻(xiàn)1830條經(jīng)驗(yàn) 獲得超3個(gè)贊
盡管這個(gè)比較器函數(shù)存在于strings
包 (?strings.Compare()
) 中,但它的文檔也建議不要使用它:
Compare 返回一個(gè)按字典順序比較兩個(gè)字符串的整數(shù)。如果 a==b,結(jié)果將為 0,如果 a < b,則結(jié)果為 -1,如果 a > b,則結(jié)果為 +1。
包含比較只是為了與包字節(jié)對(duì)稱。使用內(nèi)置的字符串比較運(yùn)算符 ==、<、> 等通常更清晰、更快。
為什么不實(shí)用strings.Compare()
?
有幾個(gè)原因。
首先,在這種Compare()
實(shí)用/常見的語言中,通常這些語言支持完全基于具有此簽名的函數(shù)的排序。
例如,在 Java 中有一個(gè)Comparator
接口,您可以將其傳遞給Collections.sort()
.?因此,在 Java 中,您被迫擁有/實(shí)現(xiàn)這種比較(返回-1
,0
或1
)。
在 Go 中,排序不是基于這樣的比較函數(shù)。在 Go 中,排序是基于一個(gè)Less(i, j int) bool
基本比較的函數(shù)a[i] < a[j]
,它只是“是不是少了?”。為此,你不需要strings.Compare()
,你只需要a < b
。
第二個(gè)原因:strings.Compare()
沒有刻意優(yōu)化,所以你不習(xí)慣使用它。的實(shí)施strings.Compare()
有這樣的評(píng)論:
// NOTE(rsc): This function does NOT call the runtime cmpstring function,
// because we do not want to provide any performance justification for
// using strings.Compare. Basically no one should use strings.Compare.
// As the comment above says, it is here only for symmetry with package bytes.
// If performance is important, the compiler should be changed to recognize
// the pattern so that all code doing three-way comparisons, not just code
// using strings.Compare, can benefit.
這意味著這a < b將比調(diào)用更快strings.Compare(a, b)。
第三, 的返回值strings.Compare()是一個(gè)整數(shù),攜帶是否a小于b、a等于b或a大于的信息b。如果您確實(shí)需要使用所有 3 個(gè)分支(不僅僅是“l(fā)ess”或“equal”分支),您通常需要對(duì) 的返回值做進(jìn)一步檢查,就像strings.Compare()這個(gè)簡(jiǎn)單的例子:
switch strings.Compare("a", "b") {
case -1:
? ? fmt.Println("less")
case 0:
? ? fmt.Println("equal")
case 1: // or default:
? ? fmt.Println("greater")
}
現(xiàn)在,如果您考慮一下:比較首先在內(nèi)部執(zhí)行strings.Compare(),然后在您的代碼中再次執(zhí)行(比較返回值)。這是多余的,而且性能也很差。
上面可以這樣寫(這樣會(huì)更快):
switch {
case a == b:
? ? fmt.Println("equal")
case a < b:
? ? fmt.Println("less")
default:
? ? fmt.Println("greater")
}
更多關(guān)于效率
如前所述,strings.Compare()
沒有刻意針對(duì)性能進(jìn)行優(yōu)化。但是Go的排序庫不需要-1
,?0
,1
對(duì)字符串進(jìn)行排序的結(jié)果,只需要 , 的結(jié)果a < b
即可,獲取效率與Compare()
其他語言獲取 的結(jié)果一樣。
還要注意,strings.Compare()
首先檢查是否相等a == b
,只有當(dāng)它們不相等時(shí)才進(jìn)行檢查a < b
。這一點(diǎn)很重要,因?yàn)?code>stringGo 中的值存儲(chǔ)了 the 的長(zhǎng)度string
,這意味著如果 2 個(gè)字符串的長(zhǎng)度不同,則可以立即確定它們不相等。C 和 C++ 使用\0
以 - 結(jié)尾的字符串值,這意味著判斷 2 個(gè)字符串是否相等總是需要比較整個(gè)字符串,即使一個(gè)是一千個(gè)字符而另一個(gè)是少一個(gè)。實(shí)際上這并不完全正確,因?yàn)槿绻诒容^字符時(shí)檢測(cè)到不匹配,則比較結(jié)束,但這可能仍然比比較 2 個(gè)整數(shù)慢很多。

TA貢獻(xiàn)1804條經(jīng)驗(yàn) 獲得超2個(gè)贊
Go 是由程序員為程序員設(shè)計(jì)的。如果你想要一個(gè) Cstrcmp函數(shù),用 Go 寫一個(gè)。
例如,
package main
import "fmt"
func strcmp(s1, s2 string) int {
? ? lens := len(s1)
? ? if lens > len(s2) {
? ? ? ? lens = len(s2)
? ? }
? ? for i := 0; i < lens; i++ {
? ? ? ? if s1[i] != s2[i] {
? ? ? ? ? ? return int(s1[i]) - int(s2[i])
? ? ? ? }
? ? }
? ? return len(s1) - len(s2)
}
func main() {
? ? tests := []struct {
? ? ? ? s1, s2 string
? ? ? ? cmp? ? int
? ? }{
? ? ? ? {"", "", 0},
? ? ? ? {"a", "a", 0},
? ? ? ? {"a", "b", -1},
? ? ? ? {"b", "a", +1},
? ? ? ? {"a", "aa", -1},
? ? ? ? {"aa", "a", 1},
? ? }
? ? for _, t := range tests {
? ? ? ? cmp := strcmp(t.s1, t.s2)
? ? ? ? fmt.Printf("%q %q %d %t\n", t.s1, t.s2, cmp, cmp == t.cmp)
? ? }
}
輸出:
"" "" 0 true
"a" "a" 0 true
"a" "b" -1 true
"b" "a" 1 true
"a" "aa" -1 true
"aa" "a" 1 true
GNU C 庫 (glibc):strcmp.c

TA貢獻(xiàn)1785條經(jīng)驗(yàn) 獲得超8個(gè)贊
在沒有附加函數(shù)的情況下比較字符串在 Go 中就像一個(gè)魅力:
log.Println("as" > "ab") // true
log.Println("ab" == "ab") // true
log.Println("abc" < "abd") // true
回答您的問題:如果您想使用任何類型的函數(shù)(例如strings.Compare),那么您將獲得一個(gè)具有三種狀態(tài)的變量(即-1, 0, 1),最終您將不得不比較這三種狀態(tài)。因此,當(dāng)我們談?wù)撟址容^時(shí),您無法避免比較少于兩次。
- 3 回答
- 0 關(guān)注
- 175 瀏覽
添加回答
舉報(bào)