Wie vergleiche ich Strings in GoLang?

88

Ich kann beim Vergleich der Go-Zeichenfolgen kein "echtes" Ergebnis erzielen. Ich habe Folgendes geschrieben, um das Problem zu erklären, und einen Screenshot der Ausgabe angehängt

// 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)

}

Beispiel

user2202911
quelle
Windows-Benutzer überprüfen meine Antwort :)
Daksh Miglani

Antworten:

127

==ist der richtige Operator zum Vergleichen von Zeichenfolgen in Go. Die Zeichenfolgen, mit denen Sie aus STDIN lesen, reader.ReadStringenthalten "a"jedoch nicht , aber "a\n"(wenn Sie genau hinschauen, sehen Sie den zusätzlichen Zeilenumbruch in Ihrer Beispielausgabe).

Mit der strings.TrimRightFunktion können Sie nachgestellte Leerzeichen aus Ihrer Eingabe entfernen:

if strings.TrimRight(input, "\n") == "a" {
    // ...
}
Helmbert
quelle
9

Für plattformunabhängige Benutzer oder Windows-Benutzer können Sie Folgendes tun:

Laufzeit importieren:

import (
    "runtime"
    "strings"
)

und schneiden Sie dann die Saite wie folgt:

if runtime.GOOS == "windows" {
  input = strings.TrimRight(input, "\r\n")
} else {
  input = strings.TrimRight(input, "\n")
}

Jetzt können Sie es so vergleichen:

if strings.Compare(input, "a") == 0 {
  //....yourCode
}

Dies ist ein besserer Ansatz, wenn Sie STDIN auf mehreren Plattformen verwenden.

Erläuterung

Dies geschieht, weil unter Windows Zeilen enden, "\r\n"die als CRLF bezeichnet werden, aber unter UNIX Zeilen enden, "\n"die als LF bezeichnet werden, und deshalb "\n"auf Unix-basierten Betriebssystemen trimmen, während wir "\r\n"auf Windows trimmen .

Daksh Miglani
quelle
4
Es besteht keine Notwendigkeit zu unterscheiden. Das zweite Argument ist ein Cutset, kein Suffix, und alle Zeichen im Cutset werden in beliebiger Reihenfolge / Kombination abgeschnitten. Das Trimmen von "\ r \ n" reicht für beide aus.
Jason Carlson
1

Angenommen, es gibt keine vorangestellten / nachfolgenden Leerzeichen, gibt es immer noch einige Möglichkeiten, die Zeichenfolgengleichheit zu bestätigen. Einige davon sind:

Hier sind einige grundlegende Benchmark-Ergebnisse (in diesen Tests strings.EqualFold(.., ..)scheint dies die leistungsstärkste Wahl zu sein):

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

Da es einige Optionen gibt, finden Sie hier den Code zum Generieren von Benchmarks.

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)
    }
}
Debosmit Ray
quelle
0

Der Inhalt von Zeichenfolgen in Golang kann mit dem ==Operator verglichen werden . Wenn die Ergebnisse nicht wie es zu erwarten kann einige versteckten Zeichen lang sein wie \n, \r, Räume, etc. So als Faustregel, versuchen , diese unter Verwendung von Funktionen zur Verfügung gestellt , indem stringsPaket in golang.

Zum Beispiel können Leerzeichen mit der strings.TrimSpaceFunktion entfernt werden . Sie können auch eine benutzerdefinierte Funktion definieren, um alle benötigten Zeichen zu entfernen. strings.TrimFuncFunktion kann Ihnen mehr Leistung geben.

Abhishek Srivastava
quelle