Golang 比较两个字符串包含相同的词

Golang Compare Two Strings contains same words

我正在尝试检查一个数组是否包含另一个数组的特定单词,如下所示:

我将如何在 golang 中执行此操作。我尝试了一系列步骤,但我回到了原点,到目前为止我所拥有的是:

func compare(firstString, secondString string) bool {
    return false
}

compare("3 of hearts", "5 of hearts")
## This should return true
func compare(f, s string) bool {
    arr1, arr2 := strings.Split(f, " "), strings.Split(s, " ")
    for _, v1 := range arr1 {
        for _, v2 := range arr2 {
            if v1 == v2 {
                return true
            }
        }
    }
    return false
}

go playground

我是 golang 的新手,但无需循环两次即可获得此信息的最佳方法是:

func compare(firstString, secondString string) bool {
    f, s := strings.Split(f, " "), strings.Split(secondString, " ")
    if f[0] == s[0] || f[2] == f[2] {
        return true
    }
    return false
}

compare("3 of hearts", "5 of hearts")
## This should return true

compare("7 of hearts", "7 of clubs")
## This should return true

compare("Jack of spades", "Jack of spades")
## This should return true

compare("5 of hearts", "7 of clubs")
## This should return false

我不知道你到底想做什么。 (我的意思是你好世界很无聊) 不过从问题来看,至少我知道可能和扑克有关。

所以你应该先设计扑克牌相关的结构

然后你需要一个方法来从字符串中获取对象

最后,设计一个卡片的Equal功能,至此大功告成。


  1. type Card struct{}
  2. func GetCardFromStr(str string) (*Card, error)
  3. func (card *Card) Equal(card2 *Card, criteria criteria) bool

示例代码

package main

import (
    "fmt"
    "strconv"
    "strings"
)

type Suit uint8

const (
    Spades Suit = iota + 1
    Hearts
    Diamonds
    Clubs
)

var suitMap map[string]Suit

func init() {
    suitMap = map[string]Suit{"spades": Spades, "hearts": Hearts, "diamonds": Diamonds, "clubs": Clubs}
}

func StrToSuit(str string) Suit {
    if suit, exists := suitMap[strings.ToLower(str)]; exists {
        return suit
    }
    return 0
}

type Card struct {
    point int  // 1-13 // ace, 2 to 10, Jack J, Queen Q, King K
    suit  Suit // spades ♠️, hearts ♥️, diamonds ♦️, clubs ♣️ // emoji suit: https://emojipedia.org/search/?q=Suit
}

func NewCard(point int, suit Suit) (*Card, error) {
    if point < 0 || point > 13 {
        return nil, fmt.Errorf("illegal point: '%d', it should in the range: 1~13", point)
    }
    return &Card{point, suit}, nil // you can consider checking the suit.
}

func (card *Card) String() string {
    return fmt.Sprintf("%s%d", map[Suit]string{
        Spades:   "♠️",
        Hearts:   "♥️",
        Diamonds: "♦️",
        Clubs:    "♣️",
    }[card.suit], card.point)
}

type criteria uint8

const (
    Loose criteria = 1 << iota // one of them match
    // ... // others
    Strict // all match
)

func (card *Card) Equal(card2 *Card, criteria criteria) bool {
    if criteria == Strict {
        if card.point == card2.point && (card.suit == card2.suit && card.suit != 0) {
            return true
        }
        return false
    }
    if card.point == card2.point || (card.suit == card2.suit && card.suit != 0) {
        return true
    }
    return false
}

func GetCardFromStr(str string) (*Card, error) {
    slice := strings.Split(str, " ")
    if slice == nil {
        return nil, fmt.Errorf("can't convert string to the card")
    }
    alphaMap := map[string]int{
        "ace":  1,
        "jack": 11, "queen": 12, "king": 13,
    }
    cardPoint := 0
    var cardSuit Suit
    for _, elem := range slice {
        elem = strings.ToLower(elem)
        if cardPoint == 0 {
            checkPoint := true
            if point, exists := alphaMap[elem]; exists {
                cardPoint = point
                checkPoint = false
            }
            if checkPoint {
                if point, err := strconv.Atoi(elem); err == nil {
                    cardPoint = point
                }
            }
        }
        if cardSuit == 0 {
            if suit := StrToSuit(elem); suit != 0 {
                cardSuit = suit
            }
        }
    }

    if cardPoint == 0 {
        return nil, fmt.Errorf("can't convert string to the card (unknown point)")
    }
    if cardSuit == 0 {
        return nil, fmt.Errorf("can't convert string to the card (unknown suit)")
    }

    return NewCard(cardPoint, cardSuit)
}

func main() {
    for caseNumber, data := range []struct {
        s1 string
        s2 string
        criteria
    }{
        {"-5 hearts", "5 hearts", Loose},                                            // error illegal point: '-5', it should in the range: 1~13
        {"0", "", Loose},                                                            // error can't convert string to the card (unknown point)
        {"3 of hearts", "3 of hearts", Loose},                                       // true
        {"3 of hearts", "5 of hearts", Loose},                                       // true
        {"7 of hearts", "7 of clubs", Loose},                                        // true
        {"Jack of spades", "Jack of spades", Strict},                                // true
        {"Jack of spades", "Jack spades", Strict},                                   // true
        {"Jack of spades", "Jack hearts", Strict},                                   // false
        {"Jack of spades", "Jack", Strict},                                          // error can't convert string to the card (unknown suit)
        {"Jack of spades", "spades", Strict},                                        // error can't convert string to the card (unknown point)
        {"player Foo: 1 of clubs ", "player bar: I get an Ace of spades !!", Loose}, // true
    } {
        card1, err := GetCardFromStr(data.s1)
        if err != nil {
            fmt.Printf("case:%d errMsg:%s\n", caseNumber, err)
            continue
        }
        card2, err := GetCardFromStr(data.s2)
        if err != nil {
            fmt.Printf("case:%d errMsg:%s\n", caseNumber, err)
            continue
        }
        fmt.Printf("criteria %d, %s equal %s: %v\n",
            data.criteria, card1, card2, card1.Equal(card2, data.criteria),
        )
    }
}

go playground

使用上面的代码,相信大家不会对比较感到困惑,也能避免downvote

然后你可以把问题转向如何优化函数GetCardFromStr 只使用loop one层、regexp 、检测更多...


严格来说,我不是在回答问题,只是为你的问题方向提供参考。希望大家不要介意,祝你好运。