Nie mogę uzyskać „prawdziwego” wyniku, jeśli chodzi o porównanie ciągów Go. Napisałem poniżej, aby wyjaśnić problem i załączyłem zrzut ekranu wyjścia
// string comparison in Go
package main
import "fmt"
import "bufio"
import "os"
func main() {
var isLetterA bool
fmt.Println("Enter the letter a")
reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('\n')
if(input == "a") {
isLetterA = true
} else {
isLetterA = false
}
fmt.Println("You entered",input)
fmt.Println("Is it the letter a?",isLetterA)
}
Odpowiedzi:
==
jest prawidłowym operatorem do porównywania ciągów w Go. Jednak ciągi, które czytasz z STDINreader.ReadString
, nie zawierają"a"
, ale"a\n"
(jeśli przyjrzysz się uważnie, zobaczysz dodatkowy podział wiersza w swoim przykładowym wyjściu).Możesz użyć tej
strings.TrimRight
funkcji, aby usunąć końcowe spacje z danych wejściowych:if strings.TrimRight(input, "\n") == "a" { // ... }
źródło
W przypadku użytkowników niezależnych od platformy lub użytkowników systemu Windows możesz:
import runtime:
import ( "runtime" "strings" )
a następnie przytnij ciąg w ten sposób:
if runtime.GOOS == "windows" { input = strings.TrimRight(input, "\r\n") } else { input = strings.TrimRight(input, "\n") }
teraz możesz to porównać w ten sposób:
if strings.Compare(input, "a") == 0 { //....yourCode }
Jest to lepsze podejście, gdy używasz STDIN na wielu platformach.
Wyjaśnienie
Dzieje się tak, ponieważ w
"\r\n"
systemie Windows linie kończą się tym, co jest znane jako CRLF, ale w liniach systemu UNIX,"\n"
którym jest znany jako LF, i dlatego przycinamy"\n"
w systemach operacyjnych opartych na unixie, podczas gdy przycinamy"\r\n"
w systemie Windows.źródło
Zakładając, że nie ma poprzedzających / następujących po sobie białych znaków, nadal istnieje kilka sposobów zapewnienia równości ciągów. Oto niektóre z nich:
strings.ToLower(..)
następnie==
strings.EqualFold(.., ..)
cases#Lower
sparowane z==
cases#Fold
sparowane z==
Oto kilka podstawowych wyników testów porównawczych (w tych testach
strings.EqualFold(.., ..)
wydaje się , że jest to najbardziej skuteczny wybór):goos: darwin goarch: amd64 BenchmarkStringOps/both_strings_equal::equality_op-4 10000 182944 ns/op BenchmarkStringOps/both_strings_equal::strings_equal_fold-4 10000 114371 ns/op BenchmarkStringOps/both_strings_equal::fold_caser-4 10000 2599013 ns/op BenchmarkStringOps/both_strings_equal::lower_caser-4 10000 3592486 ns/op BenchmarkStringOps/one_string_in_caps::equality_op-4 10000 417780 ns/op BenchmarkStringOps/one_string_in_caps::strings_equal_fold-4 10000 153509 ns/op BenchmarkStringOps/one_string_in_caps::fold_caser-4 10000 3039782 ns/op BenchmarkStringOps/one_string_in_caps::lower_caser-4 10000 3861189 ns/op BenchmarkStringOps/weird_casing_situation::equality_op-4 10000 619104 ns/op BenchmarkStringOps/weird_casing_situation::strings_equal_fold-4 10000 148489 ns/op BenchmarkStringOps/weird_casing_situation::fold_caser-4 10000 3603943 ns/op BenchmarkStringOps/weird_casing_situation::lower_caser-4 10000 3637832 ns/op
Ponieważ istnieje wiele opcji, oto kod do generowania testów porównawczych.
package main import ( "fmt" "strings" "testing" "golang.org/x/text/cases" "golang.org/x/text/language" ) func BenchmarkStringOps(b *testing.B) { foldCaser := cases.Fold() lowerCaser := cases.Lower(language.English) tests := []struct{ description string first, second string }{ { description: "both strings equal", first: "aaaa", second: "aaaa", }, { description: "one string in caps", first: "aaaa", second: "AAAA", }, { description: "weird casing situation", first: "aAaA", second: "AaAa", }, } for _, tt := range tests { b.Run(fmt.Sprintf("%s::equality op", tt.description), func(b *testing.B) { for i := 0; i < b.N; i++ { benchmarkStringEqualsOperation(tt.first, tt.second, b) } }) b.Run(fmt.Sprintf("%s::strings equal fold", tt.description), func(b *testing.B) { for i := 0; i < b.N; i++ { benchmarkStringsEqualFold(tt.first, tt.second, b) } }) b.Run(fmt.Sprintf("%s::fold caser", tt.description), func(b *testing.B) { for i := 0; i < b.N; i++ { benchmarkStringsFoldCaser(tt.first, tt.second, foldCaser, b) } }) b.Run(fmt.Sprintf("%s::lower caser", tt.description), func(b *testing.B) { for i := 0; i < b.N; i++ { benchmarkStringsLowerCaser(tt.first, tt.second, lowerCaser, b) } }) } } func benchmarkStringEqualsOperation(first, second string, b *testing.B) { for n := 0; n < b.N; n++ { _ = strings.ToLower(first) == strings.ToLower(second) } } func benchmarkStringsEqualFold(first, second string, b *testing.B) { for n := 0; n < b.N; n++ { _ = strings.EqualFold(first, second) } } func benchmarkStringsFoldCaser(first, second string, caser cases.Caser, b *testing.B) { for n := 0; n < b.N; n++ { _ = caser.String(first) == caser.String(second) } } func benchmarkStringsLowerCaser(first, second string, caser cases.Caser, b *testing.B) { for n := 0; n < b.N; n++ { _ = caser.String(first) == caser.String(second) } }
źródło
Zawartość wewnątrz stringów w Golangu można porównać za pomocą
==
operatora. Jeśli wyniki nie są zgodnie z oczekiwaniami mogą istnieć pewne ukryte znaki takie jak\n
,\r
spacje itp Więc jako ogólna zasada, spróbuj usunąć te, za pomocą funkcji oferowanych przezstrings
pakiet w golang.Na przykład spacje można usunąć za pomocą
strings.TrimSpace
funkcji. Możesz także zdefiniować funkcję niestandardową, aby usunąć dowolny znak, którego potrzebujesz.strings.TrimFunc
funkcja może dać ci więcej mocy.źródło