Come si confrontano le stringhe in GoLang?


93

Non sono in grado di produrre un risultato "vero" quando si tratta di confrontare le stringhe Go. Ho scritto quanto segue per spiegare il problema e allegato uno screenshot dell'output

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

}

esempio


gli utenti di Windows controllano la mia risposta :)
Daksh Miglani

Risposte:


132

==è l'operatore corretto per confrontare le stringhe in Go. Tuttavia, le stringhe che leggi da STDIN con reader.ReadStringnon contengono "a", ma "a\n"(se guardi da vicino, vedrai l'interruzione di riga aggiuntiva nell'output di esempio).

È possibile utilizzare la strings.TrimRightfunzione per rimuovere gli spazi vuoti finali dall'input:

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

9

Per gli utenti indipendenti dalla piattaforma o gli utenti Windows, ciò che puoi fare è:

runtime di importazione:

import (
    "runtime"
    "strings"
)

e poi ritaglia la stringa in questo modo:

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

ora puoi confrontarlo in questo modo:

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

Questo è un approccio migliore quando utilizzi STDIN su più piattaforme.

Spiegazione

Questo accade perché su Windows le righe terminano con la "\r\n"quale è nota come CRLF, ma su UNIX le righe terminano con la "\n"quale è nota come LF ed è per questo che rifiniamo "\n"su sistemi operativi basati su unix mentre "\r\n"su Windows.


4
Non è necessario differenziare. Il secondo argomento è un cutset, non un suffisso, e qualsiasi carattere nel cutset verrà tagliato, in qualsiasi ordine / combinazione. Il taglio di "\ r \ n" sarà sufficiente su entrambi.
Jason Carlson,

1

Supponendo che non ci siano caratteri di spazi bianchi anteposti / successivi, ci sono ancora alcuni modi per affermare l'uguaglianza delle stringhe. Alcuni di questi sono:

Ecco alcuni risultati di benchmark di base (in questi test, strings.EqualFold(.., ..)sembra la scelta più performante):

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

Poiché ci sono alcune opzioni, ecco il codice per generare benchmark.

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

0

Il contenuto all'interno delle stringhe in Golang può essere confrontato utilizzando l' ==operatore. Se i risultati non sono come previsto ci possono essere alcuni caratteri nascosti, come \n, \r, spazi, ecc Quindi, come regola generale, provare a rimuovere quelli che utilizzano le funzioni fornite da stringspackage in golang.

Ad esempio, gli spazi possono essere rimossi utilizzando la strings.TrimSpacefunzione. Puoi anche definire una funzione personalizzata per rimuovere qualsiasi carattere di cui hai bisogno. strings.TrimFuncla funzione può darti più potere.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.