英文:
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
scontains a character other than0or4, the result will be undefined (depending on the position of that character). If you need to ensure whether the input only contains0or4, 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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论