¿Cómo comparo cadenas en GoLang?

88

No puedo producir un resultado 'verdadero' cuando se trata de la comparación de cadenas Go. Escribí lo siguiente para explicar el problema y adjunté una captura de pantalla del resultado.

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

}

ejemplo

user2202911
fuente
los usuarios de Windows comprueban mi respuesta :)
Daksh Miglani

Respuestas:

127

==es el operador correcto para comparar cadenas en Go. Sin embargo, las cadenas que lee de STDIN con reader.ReadStringno contienen "a", pero "a\n"(si observa de cerca, verá el salto de línea adicional en su salida de ejemplo).

Puede usar la strings.TrimRightfunción para eliminar los espacios en blanco finales de su entrada:

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

Para los usuarios independientes de la plataforma o los usuarios de Windows, lo que puede hacer es:

tiempo de ejecución de importación:

import (
    "runtime"
    "strings"
)

y luego recorta la cuerda así:

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

ahora puedes compararlo así:

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

Este es un mejor enfoque cuando utiliza STDIN en múltiples plataformas.

Explicación

Esto sucede porque en Windows las líneas terminan con lo "\r\n"que se conoce como CRLF, pero en UNIX las líneas terminan con lo "\n"que se conoce como LF y por eso recortamos "\n"en sistemas operativos basados ​​en Unix mientras que recortamos "\r\n"en Windows.

Daksh Miglani
fuente
4
No es necesario diferenciar. El segundo argumento es un conjunto de cortes, no un sufijo, y todos los caracteres del conjunto de cortes se recortarán, en cualquier orden o combinación. Recortar "\ r \ n" será suficiente en ambos.
Jason Carlson
1

Suponiendo que no hay caracteres de espacio en blanco antepuestos / sucesivos, todavía hay algunas formas de afirmar la igualdad de cadenas. Algunos de ellos son:

A continuación, se muestran algunos resultados comparativos básicos (en estas pruebas, strings.EqualFold(.., ..)parece ser la opción con mayor rendimiento):

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

Dado que hay bastantes opciones, aquí está el código para generar puntos de referencia.

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
fuente
0

El contenido dentro de las cadenas en Golang se puede comparar usando el ==operador. Si los resultados no son los esperados puede haber algunos caracteres ocultos como \n, \r, espacios, etc. Así como regla general, intente quitar los que utilizan las funciones proporcionadas por stringsel paquete en golang.

Por ejemplo, los espacios se pueden eliminar usando strings.TrimSpacefunction. También puede definir una función personalizada para eliminar cualquier carácter que necesite. strings.TrimFuncLa función puede darte más poder.

Abhishek Srivastava
fuente