GoLang. I want to check the string for its contents for a criteria. How to do it in GoLang efficiently in terms of speed?

huangapple go评论92阅读模式
英文:

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 (
	&quot;regexp&quot;
)

func check(s string) bool {
	return regexp.MustCompile(`^4+0*$`).MatchString(s)
}

func main() {
	for _, tt := range []string{&quot;444&quot;, &quot;44&quot;, &quot;40&quot;, &quot;4400&quot;, &quot;4440&quot;} {
		if !check(tt) {
			panic(&quot;want true: &quot; + tt)
		}
	}
	for _, tt := range []string{&quot;404&quot;, &quot;040&quot;} {
		if check(tt) {
			panic(&quot;want false: &quot; + tt)
		}
	}
}

non-regexp

package main

func check(s string) bool {
	i := 0
	r := []rune(s)
	for i = 0; i &lt; len(r); i++ {
		if r[i] != &#39;4&#39; {
			break
		}
	}
	if i == 0 {
		return false
	}
	for ; i &lt; len(r); i++ {
		if r[i] != &#39;0&#39; {
			return false
		}
	}
	return true
}

func main() {
	for _, tt := range []string{&quot;444&quot;, &quot;44&quot;, &quot;40&quot;, &quot;4400&quot;, &quot;4440&quot;} {
		if !check(tt) {
			panic(&quot;want true: &quot; + tt)
		}
	}
	for _, tt := range []string{&quot;404&quot;, &quot;040&quot;} {
		if check(tt) {
			panic(&quot;want false: &quot; + tt)
		}
	}
}

faster version

func check(s string) bool {
	i, l := 0, len(s)
	for ; i &lt; l; i++ {
		if s[i] != &#39;4&#39; {
			break
		}
	}
	if i == 0 {
		return false
	}
	for ; i &lt; l; i++ {
		if s[i] != &#39;0&#39; {
			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 &quot;fmt&quot;

func isFourZero(s string) bool {
	i := 0
	var four bool
	for ; i &lt; len(s) &amp;&amp; s[i] == &#39;4&#39;; i++ {
		four = true
	}
	if four {
		if i &gt;= len(s) {
			return true
		}
		var zero bool
		for ; i &lt; len(s) &amp;&amp; s[i] == &#39;0&#39;; i++ {
			zero = true
		}
		if zero {
			if i &gt;= len(s) {
				return true
			}
		}
	}
	return false
}

func main() {
	tests := []struct{ s string }{
		{&quot;444&quot;}, {&quot;44&quot;}, {&quot;40&quot;}, {&quot;4400&quot;}, {&quot;4440&quot;}, {&quot;404&quot;}, {&quot;004&quot;},
	}
	for _, test := range tests {
		fmt.Printf(&quot;%q \t %t\n&quot;, test.s, isFourZero(test.s))
	}
}

Output:

&quot;444&quot; 	 true
&quot;44&quot; 	 true
&quot;40&quot; 	 true
&quot;4400&quot; 	 true
&quot;4440&quot; 	 true
&quot;404&quot; 	 false
&quot;004&quot; 	 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 (
	&quot;strings&quot;
	&quot;testing&quot;
)

var tests = []struct{ s string }{
	{&quot;444&quot;}, {&quot;44&quot;}, {&quot;40&quot;}, {&quot;4400&quot;}, {&quot;4440&quot;}, {&quot;404&quot;}, {&quot;004&quot;},
}

func BenchmarkIsFourZeroPeterSO(b *testing.B) {
	for i := 0; i &lt; b.N; i++ {
		for _, test := range tests {
			isFourZero(test.s)
		}
	}
}

func BenchmarkValidateYogeshDesai(b *testing.B) {
	for i := 0; i &lt; b.N; i++ {
		for _, test := range tests {
			validate(test.s)
		}
	}
}

func BenchmarkCheckMattn(b *testing.B) {
	for i := 0; i &lt; b.N; i++ {
		for _, test := range tests {
			check(test.s)
		}
	}
}

func isFourZero(s string) bool {
	i := 0
	var four bool
	for ; i &lt; len(s) &amp;&amp; s[i] == &#39;4&#39;; i++ {
		four = true
	}
	if four {
		if i &gt;= len(s) {
			return true
		}
		var zero bool
		for ; i &lt; len(s) &amp;&amp; s[i] == &#39;0&#39;; i++ {
			zero = true
		}
		if zero {
			if i &gt;= len(s) {
				return true
			}
		}
	}
	return false
}

func validate(str string) bool {
	if strings.HasPrefix(str, &quot;4&quot;) {
		for i := 0; i &lt; len(str)-1; i++ {
			if (str[i] == &#39;0&#39;) &amp;&amp; (str[i+1] == &#39;4&#39;) {
				return false
			}
		}

	} else {
		return false
	}
	return true
}

func check(s string) bool {
	i := 0
	r := []rune(s)
	for i = 0; i &lt; len(r); i++ {
		if r[i] != &#39;4&#39; {
			break
		}
	}
	if i == 0 {
		return false
	}
	for ; i &lt; len(r); i++ {
		if r[i] != &#39;0&#39; {
			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 (
        &quot;fmt&quot;
        &quot;strings&quot;
       )
func validate(str string) bool {

if strings.HasPrefix(str, &quot;4&quot;) {
	for i:= 0; i &lt; len(str)-1; i++ {
		if (str[i] == &#39;0&#39;) &amp;&amp; (str[i+1] == &#39;4&#39;) {
			return false
		}
	}

}else { return false }

return true
}

func main() {

data := []string{&quot;4&quot;, &quot;44&quot;, &quot;4400&quot;, &quot;4440&quot;, &quot;404&quot;, &quot;004&quot;}
      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
}

注意:

  1. 404(例如40444044040,...)是无效的
  2. 如果s包含除04之外的字符,则结果将是未定义的(取决于该字符的位置)。如果您需要确保输入只包含04,则可以使用以下函数:
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 &#39;4&#39;
    if len(s) == 0 || s[0] != &#39;4&#39; {
        return false
    }

    //INVALID: if len(s) &gt; 2 AND contains &quot;404&quot;
    for k := 2; k &lt; len(s); k++ {
        if s[k] == &#39;4&#39; &amp;&amp; s[k-1] == &#39;0&#39; &amp;&amp; s[k-2] == &#39;4&#39; {
            return false
        }
    }
    return true
}

Note:

  1. *404* (e.g. 404, 4404, 4040, ...) is INVALID.

  2. If s contains a character other than 0 or 4, the result will be undefined (depending on the position of that character). If you need to ensure whether the input only contains 0 or 4, then:

    func yetAnotherValidation2(s string) bool {
        //INVALID: if empty OR not started with &#39;4&#39;
        if len(s) == 0 || s[0] != &#39;4&#39; {
            return false
        }
    
        //INVALID: if second digit is not 0 or 4
        if len(s) &gt; 1 &amp;&amp; s[1] != &#39;0&#39; &amp;&amp; s[1] != &#39;4&#39; {
            return false
        }
    
        //For len(s) &gt; 2
        for k := 2; k &lt; len(s); k++ {
            if s[k] == &#39;4&#39; &amp;&amp; s[k-1] == &#39;0&#39; &amp;&amp; s[k-2] == &#39;4&#39; {
                return false
            } else if s[k] != &#39;0&#39; &amp;&amp; s[k] != &#39;4&#39; {
                //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

huangapple
  • 本文由 发表于 2017年6月29日 16:47:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/44820370.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定