Created
January 16, 2015 21:39
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
not foolproof, but good for a start.