ฉันจะเปรียบเทียบสตริงใน GoLang ได้อย่างไร


93

ฉันไม่สามารถสร้างผลลัพธ์ 'จริง' เมื่อพูดถึงการเปรียบเทียบสตริง Go ฉันเขียนสิ่งต่อไปนี้เพื่ออธิบายปัญหาและแนบภาพหน้าจอของผลลัพธ์

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

}

ตัวอย่าง


ผู้ใช้ windows ตรวจสอบคำตอบของฉัน :)
Daksh Miglani

คำตอบ:


132

==เป็นตัวดำเนินการที่ถูกต้องในการเปรียบเทียบสตริงใน Go อย่างไรก็ตามสตริงที่คุณอ่านจาก STDIN ด้วยreader.ReadStringจะไม่มี"a"แต่"a\n"(ถ้าคุณมองอย่างใกล้ชิดคุณจะเห็นตัวแบ่งบรรทัดพิเศษในเอาต์พุตตัวอย่างของคุณ)

คุณสามารถใช้strings.TrimRightฟังก์ชันเพื่อลบช่องว่างต่อท้ายจากอินพุตของคุณ:

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

9

สำหรับผู้ใช้แพลตฟอร์มอิสระหรือผู้ใช้ Windows สิ่งที่คุณทำได้คือ:

รันไทม์นำเข้า:

import (
    "runtime"
    "strings"
)

จากนั้นตัดแต่งสตริงดังนี้:

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

ตอนนี้คุณสามารถเปรียบเทียบได้เช่นนั้น:

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

นี่เป็นแนวทางที่ดีกว่าเมื่อคุณใช้ STDIN บนหลายแพลตฟอร์ม

คำอธิบาย

สิ่งนี้เกิดขึ้นเนื่องจากในบรรทัดของ windows ลงท้ายด้วย"\r\n"ซึ่งเรียกว่า CRLF แต่ในบรรทัด UNIX ลงท้ายด้วย"\n"ซึ่งเรียกว่า LF และนั่นคือเหตุผลที่เราตัด"\n"ต่อระบบปฏิบัติการที่ใช้ยูนิกซ์ในขณะที่เราตัดแต่ง"\r\n"บน windows


4
ไม่จำเป็นต้องแยกความแตกต่าง อาร์กิวเมนต์ที่สองคือคัตเซ็ตไม่ใช่ส่วนต่อท้ายและอักขระใด ๆ ในคัตเซ็ตจะถูกตัดแต่งตามลำดับ / การรวมกัน การตัด "\ r \ n" จะเพียงพอสำหรับทั้งสองอย่าง
Jason Carlson

1

สมมติว่าไม่มีอักขระเว้นวรรคก่อน / สำเร็จยังมีอีกสองสามวิธีในการยืนยันความเท่าเทียมกันของสตริง บางส่วน ได้แก่ :

นี่คือผลการทดสอบพื้นฐานบางส่วน (ในการทดสอบเหล่านี้strings.EqualFold(.., ..)ดูเหมือนจะเป็นตัวเลือกที่มีประสิทธิภาพมากที่สุด):

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

เนื่องจากมีตัวเลือกค่อนข้างน้อยดังนั้นนี่คือรหัสสำหรับสร้างเกณฑ์มาตรฐาน

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

เนื้อหาภายในสตริงใน Golang สามารถเปรียบเทียบได้โดยใช้==ตัวดำเนินการ หากผลจะไม่เป็นที่คาดว่าอาจจะมีบางตัวอักษรซ่อนชอบ\n, \rช่องว่าง ฯลฯ ดังนั้นเป็นกฎทั่วไปของหัวแม่มือลองเอาฟังก์ชั่นการใช้ผู้ให้บริการโดยstringsแพคเกจใน golang

สำหรับอินสแตนซ์สามารถลบช่องว่างได้โดยใช้strings.TrimSpaceฟังก์ชัน คุณยังสามารถกำหนดฟังก์ชันแบบกำหนดเองเพื่อลบอักขระที่คุณต้องการได้ strings.TrimFuncฟังก์ชั่นสามารถเพิ่มพลังให้คุณได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.