preserve order in group by filter

This commit is contained in:
facundoolano 2024-02-15 21:52:23 -03:00
parent b17dc2ad68
commit 2a5e4450b1
3 changed files with 21 additions and 10 deletions

2
go.mod
View file

@ -11,7 +11,9 @@ require (
) )
require ( require (
github.com/elliotchance/orderedmap/v2 v2.2.0 // indirect
github.com/osteele/tuesday v1.0.3 // indirect github.com/osteele/tuesday v1.0.3 // indirect
github.com/umpc/go-sortedmap v0.0.0-20180422175548-64ab94c482f4 // indirect
golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect
golang.org/x/sys v0.4.0 // indirect golang.org/x/sys v0.4.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect

5
go.sum
View file

@ -1,5 +1,7 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/elliotchance/orderedmap/v2 v2.2.0 h1:7/2iwO98kYT4XkOjA9mBEIwvi4KpGB4cyHeOFOnj4Vk=
github.com/elliotchance/orderedmap/v2 v2.2.0/go.mod h1:85lZyVbpGaGvHvnKa7Qhx7zncAdBIBq6u56Hb1PRU5Q=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/niklasfasching/go-org v1.7.0 h1:vyMdcMWWTe/XmANk19F4k8XGBYg0GQ/gJGMimOjGMek= github.com/niklasfasching/go-org v1.7.0 h1:vyMdcMWWTe/XmANk19F4k8XGBYg0GQ/gJGMimOjGMek=
@ -12,6 +14,9 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/umpc/go-sortedmap v0.0.0-20180422175548-64ab94c482f4 h1:qk1XyC6UGfPa51PGmsTQJavyhfMLScqw97pEV3sFClI=
github.com/umpc/go-sortedmap v0.0.0-20180422175548-64ab94c482f4/go.mod h1:X6iKjXCleSyo/LZzKZ9zDF/ZB2L9gC36I5gLMf32w3M=
github.com/yuin/goldmark v1.7.0 h1:EfOIvIMZIzHdB/R/zVrikYLPPwJlfMcNczJFMs1m6sA= github.com/yuin/goldmark v1.7.0 h1:EfOIvIMZIzHdB/R/zVrikYLPPwJlfMcNczJFMs1m6sA=
github.com/yuin/goldmark v1.7.0/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= github.com/yuin/goldmark v1.7.0/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw= golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw=

View file

@ -8,6 +8,7 @@ import (
"encoding/xml" "encoding/xml"
"time" "time"
"github.com/elliotchance/orderedmap/v2"
"github.com/osteele/liquid" "github.com/osteele/liquid"
"github.com/osteele/liquid/evaluator" "github.com/osteele/liquid/evaluator"
"github.com/osteele/liquid/expressions" "github.com/osteele/liquid/expressions"
@ -75,48 +76,51 @@ func groupByExpFilter(array []map[string]interface{}, name string, expr expressi
if !(rt.Kind() != reflect.Array || rt.Kind() == reflect.Slice) { if !(rt.Kind() != reflect.Array || rt.Kind() == reflect.Slice) {
return nil, nil return nil, nil
} }
groups := map[interface{}][]interface{}{} groups := orderedmap.NewOrderedMap[interface{}, []interface{}]()
for i := 0; i < rt.Len(); i++ { for i := 0; i < rt.Len(); i++ {
item := rt.Index(i).Interface() item := rt.Index(i).Interface()
key, err := expr.Bind(name, item).Evaluate() key, err := expr.Bind(name, item).Evaluate()
if err != nil { if err != nil {
return nil, err return nil, err
} }
if group, found := groups[key]; found { if group, found := groups.Get(key); found {
groups[key] = append(group, item) groups.Set(key, append(group, item))
} else { } else {
groups[key] = []interface{}{item} groups.Set(key, []interface{}{item})
} }
} }
var result []map[string]interface{} var result []map[string]interface{}
for k, v := range groups { for _, k := range groups.Keys() {
v, _ := groups.Get(k)
result = append(result, map[string]interface{}{"name": k, "items": v}) result = append(result, map[string]interface{}{"name": k, "items": v})
} }
return result, nil return result, nil
} }
// TODO use ordered map
func groupByFilter(array []map[string]interface{}, property string) []map[string]interface{} { func groupByFilter(array []map[string]interface{}, property string) []map[string]interface{} {
rt := reflect.ValueOf(array) rt := reflect.ValueOf(array)
if !(rt.Kind() != reflect.Array || rt.Kind() == reflect.Slice) { if !(rt.Kind() != reflect.Array || rt.Kind() == reflect.Slice) {
return nil return nil
} }
groups := map[interface{}][]interface{}{} groups := orderedmap.NewOrderedMap[interface{}, []interface{}]()
for i := 0; i < rt.Len(); i++ { for i := 0; i < rt.Len(); i++ {
irt := rt.Index(i) irt := rt.Index(i)
if irt.Kind() == reflect.Map && irt.Type().Key().Kind() == reflect.String { if irt.Kind() == reflect.Map && irt.Type().Key().Kind() == reflect.String {
krt := irt.MapIndex(reflect.ValueOf(property)) krt := irt.MapIndex(reflect.ValueOf(property))
if krt.IsValid() && krt.CanInterface() { if krt.IsValid() && krt.CanInterface() {
key := krt.Interface() key := krt.Interface()
if group, found := groups[key]; found { if group, found := groups.Get(key); found {
groups[key] = append(group, irt.Interface()) groups.Set(key, append(group, irt.Interface()))
} else { } else {
groups[key] = []interface{}{irt.Interface()} groups.Set(key, []interface{}{irt.Interface()})
} }
} }
} }
} }
var result []map[string]interface{} var result []map[string]interface{}
for k, v := range groups { for _, k := range groups.Keys() {
v, _ := groups.Get(k)
result = append(result, map[string]interface{}{"name": k, "items": v}) result = append(result, map[string]interface{}{"name": k, "items": v})
} }
return result return result