douzhao7445
2016-07-29 08:46
浏览 1.3k
已采纳

如何在golang切片中搜索元素

I have a slice of structs.

type Config struct {
    Key string
    Value string
}

// I form a slice of the above struct
var myconfig []Config 

// unmarshal a response body into the above slice
if err := json.Unmarshal(respbody, &myconfig); err != nil {
    panic(err)
}

fmt.Println(config)

Here is the output of this:

[{key1 test} {web/key1 test2}]

How can I search this array to get the element where key="key1"?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

4条回答 默认 最新

  • duande3134 2016-07-29 08:49
    已采纳

    With a simple for loop:

    for _, v := range myconfig {
        if v.Key == "key1" {
            // Found!
        }
    }
    

    Note that since element type of the slice is a struct (not a pointer), this may be inefficient if the struct type is "big" as the loop will copy each visited element into the loop variable.

    It would be faster to use a range loop just on the index, this avoids copying the elements:

    for i := range myconfig {
        if myconfig[i].Key == "key1" {
            // Found!
        }
    }
    

    Notes:

    It depends on your case whether multiple configs may exist with the same key, but if not, you should break out of the loop if a match is found (to avoid searching for others).

    for i := range myconfig {
        if myconfig[i].Key == "key1" {
            // Found!
            break
        }
    }
    

    Also if this is a frequent operation, you should consider building a map from it which you can simply index, e.g.

    // Build a config map:
    confMap := map[string]string{}
    for _, v := range myconfig {
        confMap[v.Key] = v.Value
    }
    
    // And then to find values by key:
    if v, ok := confMap["key1"]; ok {
        // Found
    }
    
    点赞 评论
  • dongxifu5009 2016-07-29 08:51

    You can save the struct into a map by matching the struct Key and Value components to their fictive key and value parts on the map:

    mapConfig := map[string]string{}
    for _, v := range myconfig {
       mapConfig[v.Key] = v.Value
    }
    

    Then using the golang comma ok idiom you can test for the key presence:

    if v, ok := mapConfig["key1"]; ok {
        fmt.Printf("%s exists", v)
    }   
    
    点赞 评论
  • douqiaotong8682 2016-07-29 08:53

    There is no library function for that. You have to code by your own.

    for _, value := range myconfig {
        if value .Key == "key1" {
            // logic
        }
    }
    

    Working code: https://play.golang.org/p/IJIhYWROP_

    package main
    
    import (
        "encoding/json"
        "fmt"
    )
    
    func main() {
        type Config struct {
            Key   string
            Value string
        }
    
        var respbody = []byte(`[
            {"Key":"Key1", "Value":"Value1"},
            {"Key":"Key2", "Value":"Value2"}
        ]`)
    
        var myconfig []Config
    
        err := json.Unmarshal(respbody, &myconfig)
        if err != nil {
            fmt.Println("error:", err)
        }
    
        fmt.Printf("%+v
    ", myconfig)
    
        for _, v := range myconfig {
            if v.Key == "Key1" {
                fmt.Println("Value: ", v.Value)
            }
        }
    
    }
    
    点赞 评论
  • dsaff82024 2018-03-29 15:38

    You can use sort.Slice() plus sort.Search()

    type Person struct {
        Name string
    }
    
    func main() {
        crowd := []Person{{"Zoey"}, {"Anna"}, {"Benni"}, {"Chris"}}
    
        sort.Slice(crowd, func(i, j int) bool {
            return crowd[i].Name <= crowd[j].Name
        })
    
        needle := "Benni"
        idx := sort.Search(len(crowd), func(i int) bool {
            return string(crowd[i].Name) >= needle
        })
    
        if crowd[idx].Name == needle {
            fmt.Println("Found:", idx, crowd[idx])
        } else {
            fmt.Println("Found noting: ", idx)
        }
    }
    

    See: https://play.golang.org/p/47OPrjKb0g_c

    点赞 评论

相关推荐 更多相似问题