Skip to content

Instantly share code, notes, and snippets.

@zgiber
Created January 16, 2015 21:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zgiber/6adf46b565cd0099e24b to your computer and use it in GitHub Desktop.
Save zgiber/6adf46b565cd0099e24b to your computer and use it in GitHub Desktop.
Filter a slice of struct based on a map with properties and values
package slicefilter
import "reflect"
import "fmt"
func Filter(src interface{}, filter map[string]interface{}, dst interface{}) error {
srcRV := reflect.ValueOf(src)
dstRV := reflect.ValueOf(dst)
if srcRV.Kind() != reflect.Slice {
return fmt.Errorf("set must be slice of struct, or slice of pointers of structs")
}
if dstRV.Kind() != reflect.Ptr {
return fmt.Errorf("dst must be pointer to slice of struct, or slice of pointers of structs")
}
dstRV = dstRV.Elem()
if dstRV.Kind() != reflect.Slice {
return fmt.Errorf("dst must be pointer to slice of struct, or slice of pointers of structs")
}
for i := 0; i < srcRV.Len(); i++ {
rv := srcRV.Index(i)
if rv.Kind() == reflect.Ptr {
rv = rv.Elem()
}
if rv.Kind() != reflect.Struct {
return fmt.Errorf("set must be a slice of structs or pointers to structs")
}
equal := true
for prop, filterValue := range filter {
field := rv.FieldByName(prop)
// check if such field exists
if field == reflect.ValueOf(nil) {
equal = false
break
}
// check if field and filter types are the same
if field.Kind() != reflect.TypeOf(filterValue).Kind() {
equal = false
break
}
// check if values are the same
if field.Interface() != filterValue {
equal = false
break
}
}
if equal {
dstRV.Set(reflect.Append(dstRV, rv))
}
}
return nil
}
@zgiber
Copy link
Author

zgiber commented Sep 9, 2015

not foolproof, but good for a start.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment