String 去比较字符串
给定两个字符串String 去比较字符串,string,go,String,Go,给定两个字符串a和b,有时我想确定以下三个语句中的哪一个是真的:ab 在C语言或C++语言中,在调用相应函数或方法后,将得到int值 v。然后,我可以通过检查v0来确定上面的哪个陈述是正确的 但在Go中,我必须至少进行两次比较(例如,首先测试a
a
和b
,有时我想确定以下三个语句中的哪一个是真的:a
,a==b
或a>b
在C语言或C++语言中,在调用相应函数或方法后,将得到int值<代码> v<代码>。然后,我可以通过检查
v<0
、v==0
或v>0
来确定上面的哪个陈述是正确的
但在Go中,我必须至少进行两次比较(例如,首先测试a
,然后测试a==b
),以确定这三种说法中哪一种是正确的
我的问题是,有没有一种方法可以让我只做一次比较
原来调用了此功能。比较函数呢
比较功能如何
即使此comparator函数存在于软件包()中,甚至其文档也建议不要使用它: Compare返回一个按字典顺序比较两个字符串的整数。如果a==b,结果为0;如果ab,结果为+1 比较仅用于与包字节对称。使用内置的字符串比较运算符==,等等,通常会更清晰、更快 为什么使用
strings.Compare()
不实用?
有几个原因
首先,在此类Compare()
实用/常见的语言中,通常这些语言支持完全基于具有此签名的函数的排序
例如,在Java中,有一个可以传递给的接口。因此,在Java中,必须进行/实现这种比较(返回-1
、0
或1
)
在Go中,排序不基于这种比较器功能。在Go排序是基于单个Less(i,j int)bool
函数的,它基本上是a[i]
比较,它只是“它是否更少?”。为此,您不需要字符串。Compare()
,您只需要a
。例如,请参见
第二个原因:strings.Compare()
不是有意优化的,所以您不习惯使用它。strings.Compare()的实现有以下注释:
// 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
将比调用字符串更快。比较(a,b)
第三,strings.Compare()
的返回值是一个整数,其中包含a
是否小于b
,或者a
是否等于b
或者a
是否大于b
的信息。如果确实需要使用所有3个分支(而不仅仅是“less”或“equal”分支),则通常需要进一步检查字符串的返回值。Compare()
,如以下简单示例所示:
switch strings.Compare("a", "b") {
case -1:
fmt.Println("less")
case 0:
fmt.Println("equal")
case 1: // or default:
fmt.Println("greater")
}
现在仔细想想:比较首先在字符串中执行。Compare()
,然后再次在代码中执行(比较返回值)。这是多余的,而且性能更低
上面可以这样写(速度更快):
开关{
案例a==b:
fmt.Println(“相等”)
案例a
更多关于效率的信息
如前所述,strings.Compare()
并没有特意针对性能进行优化。但是Go的排序库不需要排序字符串的-1
,0
,1
结果,只需要a
的结果,其获取效率与在其他语言中获取Compare()
的结果相同
还要注意的是strings.Compare()
首先检查是否相等a==b
,只有当它们不相等时,才继续检查a
。这一点很重要,因为Go中的string
值存储字符串的长度(有关详细信息,请参阅),这意味着如果两个字符串的长度不同,可以立即确定它们不相等。C和C++使用<代码> 0“< /COD>终止的字符串值”,这意味着2个字符串是否相等,总是需要比较整个字符串,即使其中一个是一千个字符,另一个则是一个。实际上,这并不是完全正确的,因为如果在比较字符时检测到不匹配,则比较结束,但这可能仍然比比较2个整数慢得多
另请参阅相关问题:即使包()中存在此comparator函数,即使其文档也建议不要使用它:
Compare返回一个按字典顺序比较两个字符串的整数。如果a==b,结果为0;如果ab,结果为+1
比较仅用于与包字节对称。使用内置的字符串比较运算符==,等等,通常会更清晰、更快
为什么使用strings.Compare()
不实用?
有几个原因
首先,在此类Compare()
实用/常见的语言中,通常这些语言支持完全基于具有此签名的函数的排序
例如,在Java中,有一个可以传递给的接口。因此,在Java中,必须进行/实现这种比较(返回-1
、0
或1
)
在Go中,排序不基于这种比较器功能。在Go排序是基于单个Less(i,j int)bool
函数的,它基本上是a[i]
比较,它只是“它是否更少?”。为此,您不需要字符串。Compare()
,您只需要a
。例如,请参见
第二个原因:strings.Compare()
不是有意优化的,所以您不习惯使用它。strings.Compare()的实现有以下注释:
// 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.
这是什么
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