过滤嵌套的结构数组

huangapple go评论78阅读模式
英文:

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 (
	&quot;encoding/json&quot;
	&quot;fmt&quot;
)

type Student struct {
	Name   string
	Age    int
	Report []*Subject
}

func (s Student) String() string {
	return fmt.Sprintf(&quot;%s(%d):%+v&quot;, s.Name, s.Age, s.Report)
}

type Subject struct {
	Name    string `json:&quot;Subject&quot;`
	Average float64
}

func (s *Subject) String() string {
	return fmt.Sprintf(&quot;%s:%f&quot;, s.Name, s.Average)
}

const DBData string = `
{
  &quot;Students&quot;: [
    {
      &quot;Name&quot;: &quot;Carson&quot;,
      &quot;Age&quot;: 30,
      &quot;Report&quot;: [
        {
          &quot;Subject&quot;: &quot;Math&quot;,
          &quot;Average&quot;: 100
        },
        {
          &quot;Subject&quot;: &quot;English&quot;,
          &quot;Average&quot;: 60
        }
      ]
    },
    {
      &quot;Name&quot;: &quot;Foo&quot;,
      &quot;Age&quot;: 18,
      &quot;Report&quot;: [
        {
          &quot;Subject&quot;: &quot;Math&quot;,
          &quot;Average&quot;: 60
        },
        {
          &quot;Subject&quot;: &quot;English&quot;,
          &quot;Average&quot;: 88
        }
      ]
    },
    {
      &quot;Name&quot;: &quot;Bar&quot;,
      &quot;Age&quot;: 13,
      &quot;Report&quot;: [
        {
          &quot;Subject&quot;: &quot;Math&quot;,
          &quot;Average&quot;: 91.3
        },
        {
          &quot;Subject&quot;: &quot;English&quot;,
          &quot;Average&quot;: 80.5
        }
      ]
    },
    {
      &quot;Name&quot;: &quot;Mary&quot;,
      &quot;Age&quot;: 10,
      &quot;Report&quot;: [
        {
          &quot;Subject&quot;: &quot;Math&quot;,
          &quot;Average&quot;: 95.3
        },
        {
          &quot;Subject&quot;: &quot;English&quot;,
          &quot;Average&quot;: 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), &amp;jsonObj); err != nil {
		panic(err)
	}

	students := jsonObj.Students

	filterMathExcellent := NewFilter(students, func(subjects []*Subject) bool {
		for _, s := range subjects {
			if s.Name == &quot;Math&quot; &amp;&amp; s.Average &gt; 90 {
				return true
			}
		}
		return false
	})

	// each subject score must &gt;= 80
	filterEveryGood := NewFilter(students, func(subjects []*Subject) bool {
		for _, s := range subjects {
			if s.Average &lt; 80 {
				return false
			}
		}
		return true
	})

	groupMathExcellentStudents := filterMathExcellent()
	groupEveryGoodStudents := filterEveryGood()
	fmt.Printf(&quot;%+v\n&quot;, groupMathExcellentStudents)
	fmt.Printf(&quot;%+v\n&quot;, 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 &quot;fmt&quot;
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: &quot;John&quot;, StudentNum: 1, Info: []StudentData{{Name: &quot;John&quot;, Age: 20, Report: ReportCard{Subject: &quot;Math&quot;, Average: 90}}}},
{StudentName: &quot;Jane&quot;, StudentNum: 2, Info: []StudentData{{Name: &quot;Jane&quot;, Age: 21, Report: ReportCard{Subject: &quot;English&quot;, Average: 80}}}},
{StudentName: &quot;Jack&quot;, StudentNum: 3, Info: []StudentData{{Name: &quot;Jack&quot;, Age: 22, Report: ReportCard{Subject: &quot;Science&quot;, Average: 70}}}},
{StudentName: &quot;Jill&quot;, StudentNum: 4, Info: []StudentData{{Name: &quot;Jill&quot;, Age: 23, Report: ReportCard{Subject: &quot;History&quot;, Average: 60}}}},
{StudentName: &quot;Joe&quot;, StudentNum: 5, Info: []StudentData{{Name: &quot;Joe&quot;, Age: 24, Report: ReportCard{Subject: &quot;Math&quot;, Average: 90}}}},
}
// filter the reesult to only include students with average of &gt;= 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 &gt;= average {
filtered = append(filtered, r)
}
}
}
return filtered
}

huangapple
  • 本文由 发表于 2022年6月7日 08:51:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/72524812.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定