英文:
Filtering nested array of structs
问题
我有一个返回Result数组的函数,我想创建另一个函数,它以[]Results作为输入,并应该返回[]Results作为输出。这个函数应该根据平均值过滤学生,比如只有平均分超过80的学生才应该被添加到筛选列表中。在Go语言中,我该如何实现这个功能?
func FilterStudents(results []Result) []Result {
filtered := []Result{}
for _, result := range results {
for _, data := range result.Info {
if data.Report != nil && data.Report.Average > 80 {
filtered = append(filtered, result)
break
}
}
}
return filtered
}
以上是一个示例函数,它接受一个Result数组作为参数,并返回一个经过筛选的Result数组。函数会遍历每个Result对象的Info字段,检查每个学生的ReportCard对象的Average字段是否大于80,如果是,则将该Result对象添加到筛选列表中。最后,函数返回筛选后的列表。
英文:
I have a function that returns an array of Result, I would like to create another function that takes []Results as input and should return []Results as output. this function should filter students based on Average lets say only student who have a average above 80 should be appended to filtered list how can I achieve this in go?
type Result struct {
StudentName string
StudentNum int
Info []StudentData
}
type StudentData struct {
Name string
Age int
Report *ReportCard
}
type ReportCard struct {
Subject string
Average float64
}
答案1
得分: 2
我对结构进行了轻微的更改。
对我来说,这个问题应该是根据指定的条件筛选所需的学生。
我不赞成硬编码筛选函数。我认为筛选条件非常灵活,所以我认为以下方法更合适。
func NewFilter(sData []*Student, criteriaFunc func(subjects []*Subject) bool) func() []*Student {
return func() []*Student {
result := make([]*Student, 0)
for _, curStudent := range sData {
if criteriaFunc(curStudent.Report) {
result = append(result, curStudent)
}
}
return result
}
}
完整示例
package main
import (
"encoding/json"
"fmt"
)
type Student struct {
Name string
Age int
Report []*Subject
}
func (s Student) String() string {
return fmt.Sprintf("%s(%d):%+v", s.Name, s.Age, s.Report)
}
type Subject struct {
Name string `json:"Subject"`
Average float64
}
func (s *Subject) String() string {
return fmt.Sprintf("%s:%f", s.Name, s.Average)
}
const DBData string = `
{
"Students": [
{
"Name": "Carson",
"Age": 30,
"Report": [
{
"Subject": "Math",
"Average": 100
},
{
"Subject": "English",
"Average": 60
}
]
},
{
"Name": "Foo",
"Age": 18,
"Report": [
{
"Subject": "Math",
"Average": 60
},
{
"Subject": "English",
"Average": 88
}
]
},
{
"Name": "Bar",
"Age": 13,
"Report": [
{
"Subject": "Math",
"Average": 91.3
},
{
"Subject": "English",
"Average": 80.5
}
]
},
{
"Name": "Mary",
"Age": 10,
"Report": [
{
"Subject": "Math",
"Average": 95.3
},
{
"Subject": "English",
"Average": 80.5
}
]
}
]
}
`
func NewFilter(sData []*Student, criteriaFunc func(subjects []*Subject) bool) func() []*Student {
return func() []*Student {
result := make([]*Student, 0)
for _, curStudent := range sData {
if criteriaFunc(curStudent.Report) {
result = append(result, curStudent)
}
}
return result
}
}
func main() {
var jsonObj struct {
Students []*Student
}
if err := json.Unmarshal([]byte(DBData), &jsonObj); err != nil {
panic(err)
}
students := jsonObj.Students
filterMathExcellent := NewFilter(students, func(subjects []*Subject) bool {
for _, s := range subjects {
if s.Name == "Math" && s.Average > 90 {
return true
}
}
return false
})
// each subject score must >= 80
filterEveryGood := NewFilter(students, func(subjects []*Subject) bool {
for _, s := range subjects {
if s.Average < 80 {
return false
}
}
return true
})
groupMathExcellentStudents := filterMathExcellent()
groupEveryGoodStudents := filterEveryGood()
fmt.Printf("%+v\n", groupMathExcellentStudents)
fmt.Printf("%+v\n", groupEveryGoodStudents)
}
<kbd>go playground</kbd>
英文:
I made a slight change to the structure.
For me, this question should be
Filter the desired students according to the specified criteria.
I don't advocate hard coding of filter functions. I think the filtering conditions are very flexible, so I think the following method is more appropriate.
func NewFilter(sData []*Student, criteriaFunc func(subjects []*Subject) bool) func() []*Student {
return func() []*Student {
result := make([]*Student, 0)
for _, curStudent := range sData {
if criteriaFunc(curStudent.Report) {
result = append(result, curStudent)
}
}
return result
}
}
Full Example
package main
import (
"encoding/json"
"fmt"
)
type Student struct {
Name string
Age int
Report []*Subject
}
func (s Student) String() string {
return fmt.Sprintf("%s(%d):%+v", s.Name, s.Age, s.Report)
}
type Subject struct {
Name string `json:"Subject"`
Average float64
}
func (s *Subject) String() string {
return fmt.Sprintf("%s:%f", s.Name, s.Average)
}
const DBData string = `
{
"Students": [
{
"Name": "Carson",
"Age": 30,
"Report": [
{
"Subject": "Math",
"Average": 100
},
{
"Subject": "English",
"Average": 60
}
]
},
{
"Name": "Foo",
"Age": 18,
"Report": [
{
"Subject": "Math",
"Average": 60
},
{
"Subject": "English",
"Average": 88
}
]
},
{
"Name": "Bar",
"Age": 13,
"Report": [
{
"Subject": "Math",
"Average": 91.3
},
{
"Subject": "English",
"Average": 80.5
}
]
},
{
"Name": "Mary",
"Age": 10,
"Report": [
{
"Subject": "Math",
"Average": 95.3
},
{
"Subject": "English",
"Average": 80.5
}
]
}
]
}
`
func NewFilter(sData []*Student, criteriaFunc func(subjects []*Subject) bool) func() []*Student {
return func() []*Student {
result := make([]*Student, 0)
for _, curStudent := range sData {
if criteriaFunc(curStudent.Report) {
result = append(result, curStudent)
}
}
return result
}
}
func main() {
var jsonObj struct {
Students []*Student
}
if err := json.Unmarshal([]byte(DBData), &jsonObj); err != nil {
panic(err)
}
students := jsonObj.Students
filterMathExcellent := NewFilter(students, func(subjects []*Subject) bool {
for _, s := range subjects {
if s.Name == "Math" && s.Average > 90 {
return true
}
}
return false
})
// each subject score must >= 80
filterEveryGood := NewFilter(students, func(subjects []*Subject) bool {
for _, s := range subjects {
if s.Average < 80 {
return false
}
}
return true
})
groupMathExcellentStudents := filterMathExcellent()
groupEveryGoodStudents := filterEveryGood()
fmt.Printf("%+v\n", groupMathExcellentStudents)
fmt.Printf("%+v\n", groupEveryGoodStudents)
}
<kbd>go playground</kbd>
答案2
得分: 0
package main
import "fmt"
type Result struct {
StudentName string
StudentNum int
Info []StudentData
}
type StudentData struct {
Name string
Age int
Report ReportCard
}
type ReportCard struct {
Subject string
Average float64
}
func main() {
// 创建一个新的 Result 结构体
result := []Result{
{StudentName: "John", StudentNum: 1, Info: []StudentData{{Name: "John", Age: 20, Report: ReportCard{Subject: "Math", Average: 90}}}},
{StudentName: "Jane", StudentNum: 2, Info: []StudentData{{Name: "Jane", Age: 21, Report: ReportCard{Subject: "English", Average: 80}}}},
{StudentName: "Jack", StudentNum: 3, Info: []StudentData{{Name: "Jack", Age: 22, Report: ReportCard{Subject: "Science", Average: 70}}}},
{StudentName: "Jill", StudentNum: 4, Info: []StudentData{{Name: "Jill", Age: 23, Report: ReportCard{Subject: "History", Average: 60}}}},
{StudentName: "Joe", StudentNum: 5, Info: []StudentData{{Name: "Joe", Age: 24, Report: ReportCard{Subject: "Math", Average: 90}}}},
}
// 过滤结果,只包含平均分大于等于 80 的学生
result = filter(result, 80)
fmt.Println(result)
}
func filter(result []Result, average float64) []Result {
var filtered []Result
for _, r := range result {
for _, s := range r.Info {
if s.Report.Average >= average {
filtered = append(filtered, r)
}
}
}
return filtered
}
英文:
package main
import "fmt"
type Result struct {
StudentName string
StudentNum int
Info []StudentData
}
type StudentData struct {
Name string
Age int
Report ReportCard
}
type ReportCard struct {
Subject string
Average float64
}
func main() {
// Create a new Result struct
result := []Result{
{StudentName: "John", StudentNum: 1, Info: []StudentData{{Name: "John", Age: 20, Report: ReportCard{Subject: "Math", Average: 90}}}},
{StudentName: "Jane", StudentNum: 2, Info: []StudentData{{Name: "Jane", Age: 21, Report: ReportCard{Subject: "English", Average: 80}}}},
{StudentName: "Jack", StudentNum: 3, Info: []StudentData{{Name: "Jack", Age: 22, Report: ReportCard{Subject: "Science", Average: 70}}}},
{StudentName: "Jill", StudentNum: 4, Info: []StudentData{{Name: "Jill", Age: 23, Report: ReportCard{Subject: "History", Average: 60}}}},
{StudentName: "Joe", StudentNum: 5, Info: []StudentData{{Name: "Joe", Age: 24, Report: ReportCard{Subject: "Math", Average: 90}}}},
}
// filter the reesult to only include students with average of >= 80
result = filter(result, 80)
fmt.Println(result)
}
func filter(result []Result, average float64) []Result {
var filtered []Result
for _, r := range result {
for _, s := range r.Info {
if s.Report.Average >= average {
filtered = append(filtered, r)
}
}
}
return filtered
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论