Let's say I've got the following structs:
type A struct {
Field1 string
Field2 string
}
type B struct {
Field3 string
Field4 int
}
and one more struct which uses the previous two:
type C struct {
A
MyList []B
}
Now, I've got some data that I want to group and map into a C
struct and return a slice of C
:
var results []C
I've got a slice of structs that looks like (since it's a slice if could happen that we have repeated A):
type X struct {
A
B
}
So I want to group the results by A. To do so I'm gonna iterate through a slice of X that my method receive as parameter:
var results []C
// Y is an slice of Xs
for _, elem := range Y {
// If elem.A exists then append elem.B into C.A
// If not then add elem.A and elem.B into C
}
How can achieve the stuff stated in the comments above? I mean, how could I check if a struct A
exists already in the slice of structs C
?
CodePudding user response:
Usually when you want to aggregate something by some value, you use a map. The key will be the value you want to aggregate by, type of A
in your case.
This is easiest here too, this only requires the key type to be comparable.
You may simply gather the data like this:
// Example data:
xs := []X{
{A{"a1", "a2"}, B{"b1", 2}},
{A{"a1", "a2"}, B{"b11", 22}},
{A{"a1", "a3"}, B{"b4", 5}},
}
m := map[A][]B{}
for _, x := range xs {
m[x.A] = append(m[x.A], x.B)
}
fmt.Println(m)
This will output:
map[{a1 a2}:[{b1 2} {b11 22}] {a1 a3}:[{b4 5}]]
If you do need the result as []C
, iterate over the map and populate it:
for a, bs := range m {
results = append(results, C{a, bs})
}
fmt.Println(results)
This will output:
[{{a1 a2} [{b1 2} {b11 22}]} {{a1 a3} [{b4 5}]}]
Try the examples on the Go Playground.
If by any chance A
wouldn't be comparable, you would have to resort to using loops instead of map lookups where you would have to manually check for equivalence, and if you find a match, you'd perform the append operation.