英文:
Golang Check for existing items in slice of structs
问题
假设我有以下结构体:
type A struct {
Field1 string
Field2 string
}
type B struct {
Field3 string
Field4 int
}
还有一个使用前两个结构体的结构体:
type C struct {
A
MyList []B
}
现在,我有一些数据,我想将其分组并映射到一个 C
结构体中,并返回一个 C
的切片:
var results []C
我有一个结构体切片,看起来像这样(由于它是一个切片,可能会有重复的 A):
type X struct {
A
B
}
所以我想按 A 进行分组。为此,我将遍历一个作为参数传递给我的方法的 X 结构体切片:
var results []C
// Y 是一个 X 的切片
for _, elem := range Y {
// 如果 elem.A 已经存在,则将 elem.B 添加到 C.A 中
// 如果不存在,则将 elem.A 和 elem.B 添加到 C 中
}
如何实现上述注释中的内容?也就是说,我如何检查结构体 A
是否已经存在于结构体切片 C
中?
英文:
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
?
答案1
得分: 3
通常,当你想按某个值进行聚合时,你会使用一个映射(map)。键将是你想要按其聚合的值,在你的情况下是类型为A
的值。
在这里也是最简单的方法,只需要键的类型是可比较的。
你可以像这样简单地收集数据:
// 示例数据:
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)
这将输出:
map[{a1 a2}:[{b1 2} {b11 22}] {a1 a3}:[{b4 5}]]
如果你确实需要将结果作为[]C
,可以遍历映射并填充它:
for a, bs := range m {
results = append(results, C{a, bs})
}
fmt.Println(results)
这将输出:
[{{a1 a2} [{b1 2} {b11 22}]} {{a1 a3} [{b4 5}]}]
你可以在Go Playground上尝试这些示例。
如果不巧的是,A
不可比较,你将不得不使用循环而不是映射查找,你需要手动检查是否相等,如果找到匹配项,执行追加操作。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论