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
}
CodePudding user response:
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)
}
CodePudding user response:
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
}