英文:
GoLang. I want to check the string for its contents for a criteria. How to do it in GoLang efficiently in terms of speed?
问题
这个字符串只包含0或4。字符串以4开头。例如:444、44、40、4400、4440等都是有效的字符串,但404不是有效的。
目前,我正在检查0后面是否紧跟着4。我不确定这种方法是否高效。
英文:
The string will only contain 0's or 4's. The string will start with 4. example: 444, 44, 40, 4400, 4440, etc. These all are valid strings but 404 is not valid.
Currently, I am checking if 4 is present immediately after 0. I am not sure that this one is efficient one.
答案1
得分: 4
如果你指的是前导的4
和后续的0
。
使用正则表达式
package main
import (
"regexp"
)
func check(s string) bool {
return regexp.MustCompile(`^4+0*$`).MatchString(s)
}
func main() {
for _, tt := range []string{"444", "44", "40", "4400", "4440"} {
if !check(tt) {
panic("want true: " + tt)
}
}
for _, tt := range []string{"404", "040"} {
if check(tt) {
panic("want false: " + tt)
}
}
}
非正则表达式
package main
func check(s string) bool {
i := 0
r := []rune(s)
for i = 0; i < len(r); i++ {
if r[i] != '4' {
break
}
}
if i == 0 {
return false
}
for ; i < len(r); i++ {
if r[i] != '0' {
return false
}
}
return true
}
func main() {
for _, tt := range []string{"444", "44", "40", "4400", "4440"} {
if !check(tt) {
panic("want true: " + tt)
}
}
for _, tt := range []string{"404", "040"} {
if check(tt) {
panic("want false: " + tt)
}
}
}
更快的版本
func check(s string) bool {
i, l := 0, len(s)
for ; i < l; i++ {
if s[i] != '4' {
break
}
}
if i == 0 {
return false
}
for ; i < l; i++ {
if s[i] != '0' {
return false
}
}
return true
}
英文:
If you mean leading 4
and following 0
.
use regexp
package main
import (
"regexp"
)
func check(s string) bool {
return regexp.MustCompile(`^4+0*$`).MatchString(s)
}
func main() {
for _, tt := range []string{"444", "44", "40", "4400", "4440"} {
if !check(tt) {
panic("want true: " + tt)
}
}
for _, tt := range []string{"404", "040"} {
if check(tt) {
panic("want false: " + tt)
}
}
}
non-regexp
package main
func check(s string) bool {
i := 0
r := []rune(s)
for i = 0; i < len(r); i++ {
if r[i] != '4' {
break
}
}
if i == 0 {
return false
}
for ; i < len(r); i++ {
if r[i] != '0' {
return false
}
}
return true
}
func main() {
for _, tt := range []string{"444", "44", "40", "4400", "4440"} {
if !check(tt) {
panic("want true: " + tt)
}
}
for _, tt := range []string{"404", "040"} {
if check(tt) {
panic("want false: " + tt)
}
}
}
faster version
func check(s string) bool {
i, l := 0, len(s)
for ; i < l; i++ {
if s[i] != '4' {
break
}
}
if i == 0 {
return false
}
for ; i < l; i++ {
if s[i] != '0' {
return false
}
}
return true
}
答案2
得分: 1
例如,
package main
import "fmt"
func isFourZero(s string) bool {
i := 0
var four bool
for ; i < len(s) && s[i] == '4'; i++ {
four = true
}
if four {
if i >= len(s) {
return true
}
var zero bool
for ; i < len(s) && s[i] == '0'; i++ {
zero = true
}
if zero {
if i >= len(s) {
return true
}
}
}
return false
}
func main() {
tests := []struct{ s string }{
{"444"}, {"44"}, {"40"}, {"4400"}, {"4440"}, {"404"}, {"004"},
}
for _, test := range tests {
fmt.Printf("%q \t %t\n", test.s, isFourZero(test.s))
}
}
输出:
"444" true
"44" true
"40" true
"4400" true
"4440" true
"404" false
"004" false
由于我们关心速度,让我们看一些基准测试:
BenchmarkIsFourZeroPeterSO-4 10000000 201 ns/op
BenchmarkValidateYogeshDesai-4 5000000 347 ns/op
BenchmarkCheckMattn-4 2000000 602 ns/op
fourzero_test.go
:
package main
import (
"strings";
"testing";
)
var tests = []struct{ s string }{
{"444"}, {"44"}, {"40"}, {"4400"}, {"4440"}, {"404"}, {"004"},
}
func BenchmarkIsFourZeroPeterSO(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, test := range tests {
isFourZero(test.s)
}
}
}
func BenchmarkValidateYogeshDesai(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, test := range tests {
validate(test.s)
}
}
}
func BenchmarkCheckMattn(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, test := range tests {
check(test.s)
}
}
}
func isFourZero(s string) bool {
i := 0
var four bool
for ; i < len(s) && s[i] == '4'; i++ {
four = true
}
if four {
if i >= len(s) {
return true
}
var zero bool
for ; i < len(s) && s[i] == '0'; i++ {
zero = true
}
if zero {
if i >= len(s) {
return true
}
}
}
return false
}
func validate(str string) bool {
if strings.HasPrefix(str, "4") {
for i := 0; i < len(str)-1; i++ {
if (str[i] == '0') && (str[i+1] == '4') {
return false
}
}
} else {
return false
}
return true
}
func check(s string) bool {
i := 0
r := []rune(s)
for i = 0; i < len(r); i++ {
if r[i] != '4' {
break
}
}
if i == 0 {
return false
}
for ; i < len(r); i++ {
if r[i] != '0' {
return false
}
}
return true
}
英文:
For example,
package main
import "fmt"
func isFourZero(s string) bool {
i := 0
var four bool
for ; i < len(s) && s[i] == '4'; i++ {
four = true
}
if four {
if i >= len(s) {
return true
}
var zero bool
for ; i < len(s) && s[i] == '0'; i++ {
zero = true
}
if zero {
if i >= len(s) {
return true
}
}
}
return false
}
func main() {
tests := []struct{ s string }{
{"444"}, {"44"}, {"40"}, {"4400"}, {"4440"}, {"404"}, {"004"},
}
for _, test := range tests {
fmt.Printf("%q \t %t\n", test.s, isFourZero(test.s))
}
}
Output:
"444" true
"44" true
"40" true
"4400" true
"4440" true
"404" false
"004" false
Since we care about speed, let's look at some benchmarks:
BenchmarkIsFourZeroPeterSO-4 10000000 201 ns/op
BenchmarkValidateYogeshDesai-4 5000000 347 ns/op
BenchmarkCheckMattn-4 2000000 602 ns/op
fourzero_test.go
:
package main
import (
"strings"
"testing"
)
var tests = []struct{ s string }{
{"444"}, {"44"}, {"40"}, {"4400"}, {"4440"}, {"404"}, {"004"},
}
func BenchmarkIsFourZeroPeterSO(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, test := range tests {
isFourZero(test.s)
}
}
}
func BenchmarkValidateYogeshDesai(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, test := range tests {
validate(test.s)
}
}
}
func BenchmarkCheckMattn(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, test := range tests {
check(test.s)
}
}
}
func isFourZero(s string) bool {
i := 0
var four bool
for ; i < len(s) && s[i] == '4'; i++ {
four = true
}
if four {
if i >= len(s) {
return true
}
var zero bool
for ; i < len(s) && s[i] == '0'; i++ {
zero = true
}
if zero {
if i >= len(s) {
return true
}
}
}
return false
}
func validate(str string) bool {
if strings.HasPrefix(str, "4") {
for i := 0; i < len(str)-1; i++ {
if (str[i] == '0') && (str[i+1] == '4') {
return false
}
}
} else {
return false
}
return true
}
func check(s string) bool {
i := 0
r := []rune(s)
for i = 0; i < len(r); i++ {
if r[i] != '4' {
break
}
}
if i == 0 {
return false
}
for ; i < len(r); i++ {
if r[i] != '0' {
return false
}
}
return true
}
答案3
得分: 0
无正则表达式
package main
import (
"fmt"
"strings"
)
func validate(str string) bool {
if strings.HasPrefix(str, "4") {
for i := 0; i < len(str)-1; i++ {
if (str[i] == '0') && (str[i+1] == '4') {
return false
}
}
} else {
return false
}
return true
}
func main() {
data := []string{"4", "44", "4400", "4440", "404", "004"}
for _, val := range data {
fmt.Println(validate(val))
}
}
输出:
true
true
true
false
false
英文:
No RegExp
package main
import (
"fmt"
"strings"
)
func validate(str string) bool {
if strings.HasPrefix(str, "4") {
for i:= 0; i < len(str)-1; i++ {
if (str[i] == '0') && (str[i+1] == '4') {
return false
}
}
}else { return false }
return true
}
func main() {
data := []string{"4", "44", "4400", "4440", "404", "004"}
for _, val := range data {
fmt.Println(validate(val))
}
}
Output:
true
true
true
false
false
答案4
得分: 0
以下是使用单个循环的另一种实现:
func yetAnotherValidation(s string) bool {
//INVALID: 如果为空或不以'4'开头
if len(s) == 0 || s[0] != '4' {
return false
}
//INVALID: 如果len(s) > 2 并且包含"404"
for k := 2; k < len(s); k++ {
if s[k] == '4' && s[k-1] == '0' && s[k-2] == '4' {
return false
}
}
return true
}
注意:
404
(例如404
,4404
,4040
,...)是无效的。- 如果
s
包含除0
或4
之外的字符,则结果将是未定义的(取决于该字符的位置)。如果您需要确保输入只包含0
或4
,则可以使用以下函数:
func yetAnotherValidation2(s string) bool {
//INVALID: 如果为空或不以'4'开头
if len(s) == 0 || s[0] != '4' {
return false
}
//INVALID: 如果第二个数字不是0或4
if len(s) > 1 && s[1] != '0' && s[1] != '4' {
return false
}
//对于len(s) > 2
for k := 2; k < len(s); k++ {
if s[k] == '4' && s[k-1] == '0' && s[k-2] == '4' {
return false
} else if s[k] != '0' && s[k] != '4' {
//既不是0也不是4
return false
}
}
return true
}
更新:
测试和基准结果:
=== RUN TestValidate
444 true
44 true
40 true
4400 true
4440 true
404 false
004 false
--- PASS: TestValidate (0.00s)
BenchmarkYetAnotherValidation-4 50000000 38.5 ns/op
BenchmarkYetAnotherValidation2-4 30000000 45.6 ns/op
BenchmarkIsFourZero-4 20000000 54.5 ns/op
BenchmarkCheckMattn-4 10000000 144 ns/op
BenchmarkCheckMattnFast-4 30000000 50.2 ns/op
英文:
The following is another implementation using only a single loop:
func yetAnotherValidation(s string) bool {
//INVALID: if empty OR not started with '4'
if len(s) == 0 || s[0] != '4' {
return false
}
//INVALID: if len(s) > 2 AND contains "404"
for k := 2; k < len(s); k++ {
if s[k] == '4' && s[k-1] == '0' && s[k-2] == '4' {
return false
}
}
return true
}
Note:
-
*
404
* (e.g.404
,4404
,4040
, ...) is INVALID. -
If
s
contains a character other than0
or4
, the result will be undefined (depending on the position of that character). If you need to ensure whether the input only contains0
or4
, then:func yetAnotherValidation2(s string) bool { //INVALID: if empty OR not started with '4' if len(s) == 0 || s[0] != '4' { return false } //INVALID: if second digit is not 0 or 4 if len(s) > 1 && s[1] != '0' && s[1] != '4' { return false } //For len(s) > 2 for k := 2; k < len(s); k++ { if s[k] == '4' && s[k-1] == '0' && s[k-2] == '4' { return false } else if s[k] != '0' && s[k] != '4' { //Neither 0 nor 4 return false } } return true }
UPDATE:
Test and benchmark result:
=== RUN TestValidate
444 true
44 true
40 true
4400 true
4440 true
404 false
004 false
--- PASS: TestValidate (0.00s)
BenchmarkYetAnotherValidation-4 50000000 38.5 ns/op
BenchmarkYetAnotherValidation2-4 30000000 45.6 ns/op
BenchmarkIsFourZero-4 20000000 54.5 ns/op
BenchmarkCheckMattn-4 10000000 144 ns/op
BenchmarkCheckMattnFast-4 30000000 50.2 ns/op
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论