过滤具有多个参数的结构

时间:2016-09-24 21:22:58

标签: json go

我有一个结构数组和一个带有变量名和一些过滤值的地图。 我想用我的地图过滤我的数组。

示例Go Playground

package main

import "fmt"

type cnts []cnt

type cnt struct {
    ID    int    `json:"Id"`
    Area  string `json:"Area"`
    State string `json:"State"`
    City  string `json:"City"`
}

func main() {
    mycnts := cnts{
        cnt{124, "Here", "South", "Home"},
        cnt{125, "Here", "West", "Home"},
        cnt{126, "", "South", "Home"},
        cnt{127, "Here", "West", "NY"}}
    // my maps with filter
    mapFilter := map[string]string{"Area": "Here", "City": "Home"}
    fmt.Println(mapFilter)

    mycntsFilter := make(cnts, 0)
    for _, val := range mycnts {
        // I want to select only row where the map filter it's ok
        mycntsFilter = append(mycntsFilter, val)
        fmt.Println(val, mycntsFilter)
   }
}

使用动态过滤器过滤数据的最佳方法是什么(这里用字符串映射表示)?

1 个答案:

答案 0 :(得分:1)

在这种特殊情况下使用golang包反映将是最好的。

反射会为您提供结构的字段,您可以进行迭代 将它们与相应的过滤值进行比较。

示例对您提供的结构具体,但您可以使用反射轻松将其修改为应用于所有结构。

示例:Go Playground

package main

import (
        "fmt"
        "reflect"
)

type cnts []cnt

type cnt struct {
        ID    int    `json:"Id"`
        Area  string `json:"Area"`
        State string `json:"State"`
        City  string `json:"City"`
}
// Filtering function
func filterItem(val *cnt, filter map[string]string) bool {
        item := reflect.ValueOf(val).Elem()
        itemType := item.Type()
        isValid := true
        // Iterate over the struct fileds
        for i := 0; i < item.NumField(); i++ {
                field := item.Field(i)
                filterValue, ok := filter[itemType.Field(i).Name]
                if ok {
                        // filter out  
                        if filterValue != field.Interface() {
                                isValid = false
                                break
                        }
                } 

        }

        return isValid
}

func main() {
        mycnts := cnts{
                cnt{124, "Here", "South", "Home"},
                cnt{125, "Here", "West", "Home"},
                cnt{126, "", "South", "Home"},
                cnt{127, "Here", "West", "NY"}}

        // my maps with filter
        mapFilter := map[string]string{"Area": "Here", "City": "Home"}
        fmt.Println(mapFilter)

        mycntsFilter := make(cnts, 0)
        for _, val := range mycnts {
               if filterItem(&val, mapFilter) {
                      mycntsFilter = append(mycntsFilter, val)
               }
        }
        fmt.Println(mycntsFilter)
}