在 Go 中按子数组值对切片进行分组
Group slice by subarray values in Go
我有一个子数组,格式如下
Array
(
[0] => Array
(
[unit_id] => 6504
[assignment_name] => Grade assignment
[assignment_description] =>
[assignment_total_score] => 10
[unit_type_name] => Homework
[is_graded] => 1
[standard_id] => 1219
[scoring_type] => score
[attempt_score] => 8
[unit_duedate] => 2016-02-10 09:00:00
[standard] => Array
(
[0] => stdClass Object
(
[unit_id] => 6504
[is_formal] => 1
[assignment_name] => Grade assignment
[assignment_description] =>
[standard_id] => 1220
[standard_name] => 9-10.RL.3
[standard_description] => Analyze how complex characters (e.g., those with multiple or conflicting motivations) develop over the course of a
)
)
)
[1] => Array
(
[unit_id] => 8584
[assignment_name] => Sine and Cosecant Graphs
[assignment_description] => Define the sine and cosecant graphs using a unit circle
[assignment_total_score] => 15
[unit_type_name] => Paper
[scoring_type] => score
[attempt_score] => 0
[unit_duedate] => 2016-04-29 09:00:00
[standard] => Array
(
[0] => stdClass Object
(
[unit_id] => 8584
[is_formal] => 1
[assignment_name] => Sine and Cosecant Graphs
[assignment_description] => Define the sine and cosecant graphs using a unit circle
[assignment_total_score] => 15
[standard_id] => 82790
[standard_name] => 9-10.RL.7
)
)
[2] => Array
(
[unit_id] => 11611
[assignment_name] => Adding 5 + 3 + 6
[assignment_description] =>
[assignment_total_score] => 10
[unit_type_name] => Homework
[standard_id] => 82772
[scoring_type] => score
[attempt_score] => 0
[unit_duedate] => 2016-08-23 19:00:00
[standard] => Array
(
[0] => stdClass Object
(
[unit_id] => 11611
[is_formal] => 1
[assignment_name] => Adding 5 + 3 + 6
[assignment_description] =>
[assignment_total_score] => 10
[standard_id] => 82772
[standard_name] => 9-10.RL.1
)
)
)
)
我想根据每个子数组中的 unit_type_name
字段将其分组到一个新的切片中。
如何按 unit_type_name
对切片进行分组?是否有任何本机 Go 函数可用于执行此操作?
如果我循环上面的内容,那么我将得到一个重复的,我怎样才能避免这种情况?
我认为 Go 没有内置功能可以帮助你做到这一点(我可能是错的)。我的假设是 PHP 数组将转换为 JSON 对象。我设法得到下面的代码来帮助你根据 unit_type_name
对数组(JSON 格式)进行排序
我创建了两个结构,它们具有 JSON 类似于数组键的值
//StandardType ...
type StandardType struct {
UnitID int `json:"unit_id"`
IsFormal int `json:"is_formal"`
AssignmentName string `json:"assignment_name"`
AssignmentDescription string `json:"assignment_description"`
StandardID int `json:"standard_id"`
StandardName string `json:"standard_name"`
StandardDescription string `json:"standard_description"`
}
//AutoGenerated ...
type AutoGenerated struct {
UnitID int `json:"unit_id"`
AssignmentName string `json:"assignment_name"`
AssignmentDescription string `json:"assignment_description"`
AssignmentTotalScore int `json:"assignment_total_score"`
UnitTypeName string `json:"unit_type_name"`
IsGraded int `json:"is_graded"`
StandardID int `json:"standard_id"`
ScoringType string `json:"scoring_type"`
AttemptScore int `json:"attempt_score"`
UnitDuedate string `json:"unit_duedate"`
Standard []StandardType `json:"standard"`
}
var jsonData = ``
func main() {
m := []AutoGenerated{}
err := json.Unmarshal([]byte(jsonData), &m)
if err != nil {
panic(err)
}
我创建了一个地图来放置 unit_type_name
键
sliceKeys := make(map[string]string)
我还创建了映射以保存在自动生成数组中具有相似 unit_type_name
键的数组
groupedSlices := make(map[string][]AutoGenerated)
然后我遍历解码的 JSON 字符串搜索 unit_type_name
for i := range m {
如果键切片中已经存在 unit_type_name 我将数组项添加到组切片中
if _, ok := sliceKeys[m[i].UnitTypeName]; ok {
autogenerated := groupedSlices[m[i].UnitTypeName]
autogenerated = append(autogenerated, m[i])
groupedSlices[m[i].UnitTypeName] = autogenerated
} else {
否则我会创建一个新的数组键并将项目添加到其中
sliceKeys[m[i].UnitTypeName] = m[i].UnitTypeName
autogenerated := []AutoGenerated{}
autogenerated = append(autogenerated, m[i])
groupedSlices[m[i].UnitTypeName] = autogenerated
}
}
fmt.Println(sliceKeys)
fmt.Println(groupedSlices)
}
输入:
[{"unit_id": 6504,"assignment_name": "Grade assignment","assignment_description": "","assignment_total_score": 10,"unit_type_name": "Homework","is_graded": 1,"standard_id": 1219,
"scoring_type": "score","attempt_score": 8,"unit_duedate": "2016-02-10 09:00:00",
"standard": [{"unit_id": 6504,"is_formal": 1,"assignment_name": "Grade assignment","assignment_description": "",
"standard_id": 1220,"standard_name": "9-10.RL.3","standard_description": "Analyze how complex characters (e.g., those with multiple or conflicting motivations) develop over the course of a "
}]},{"unit_id": 6504,"assignment_name": "Grade assignment","assignment_description": "","assignment_total_score": 10,
"unit_type_name": "Paper","is_graded": 1,"standard_id": 1219,"scoring_type": "score","attempt_score": 8,"unit_duedate": "2016-02-10 09:00:00","standard": [{"unit_id": 6504,"is_formal": 1,"assignment_name": "Grade assignment","assignment_description": "","standard_id": 1220,"standard_name": "9-10.RL.3","standard_description": "Analyze how complex characters (e.g., those with multiple or conflicting motivations) develop over the course of a "}]},{
"unit_id": 6504,"assignment_name": "Grade assignment","assignment_description": "",
"assignment_total_score": 10,"unit_type_name": "Aything else","is_graded": 1,"standard_id": 1219,
"scoring_type": "score","attempt_score": 8,"unit_duedate": "2016-02-10 09:00:00","standard": [{
"unit_id": 6504,"is_formal": 1,"assignment_name": "Grade assignment","assignment_description": "","standard_id": 1220,
"standard_name": "9-10.RL.3","standard_description": "Analyze how complex characters (e.g., those with multiple or conflicting motivations) develop over the course of a "}]}]
输出:
map[Homework:Homework Paper:Paper Aything else:Aything else]
map[
Homework:[
{6504 Grade assignment 10 Homework 1 1219 score 8 2016-02-10 09:00:00 [{6504 1 Grade assignment 1220 9-10.RL.3 Analyze how complex characters (e.g., those with multiple or conflicting motivations) develop over the course of a }]}
]
Paper:[
{6504 Grade assignment 10 Paper 1 1219 score 8 2016-02-10 09:00:00 [{6504 1 Grade assignment 1220 9-10.RL.3 Analyze how complex characters (e.g., those with multiple or conflicting motivations) develop over the course of a }]}
]
Aything else:[
{6504 Grade assignment 10 Aything else 1 1219 score 8 2016-02-10 09:00:00 [{6504 1 Grade assignment 1220 9-10.RL.3 Analyze how complex characters (e.g., those with multiple or conflicting motivations) develop over the course of a }]}]
]
这是我写的一个通用的 GroupBy 函数:
// Created by BaiJiFeiLong@gmail.com at 2021/8/27 10:51
package main
import (
"fmt"
"reflect"
"strconv"
)
func GroupBy(arr interface{}, groupFunc interface{}) interface{} {
groupMap := reflect.MakeMap(reflect.MapOf(reflect.TypeOf(groupFunc).Out(0), reflect.TypeOf(arr)))
for i := 0; i < reflect.ValueOf(arr).Len(); i++ {
groupPivot := reflect.ValueOf(groupFunc).Call([]reflect.Value{reflect.ValueOf(arr).Index(i)})[0]
if !groupMap.MapIndex(groupPivot).IsValid() {
groupMap.SetMapIndex(groupPivot, reflect.MakeSlice(reflect.SliceOf(reflect.TypeOf(arr).Elem()), 0, 0))
}
groupMap.SetMapIndex(groupPivot, reflect.Append(groupMap.MapIndex(groupPivot), reflect.ValueOf(arr).Index(i)))
}
return groupMap.Interface()
}
func main() {
fmt.Println(GroupBy([]int{1, 22, 3, 44, 555}, func(value int) string {
return strconv.Itoa(len(strconv.Itoa(value)))
}))
}
输出:
map[1:[1 3] 2:[22 44] 3:[555]]
对于你的问题,应该是这样的代码:
group := GroupBy(items, func(item Item) string {
return item.UnitTypeName
}).(map[string][]Item)
我有一个子数组,格式如下
Array
(
[0] => Array
(
[unit_id] => 6504
[assignment_name] => Grade assignment
[assignment_description] =>
[assignment_total_score] => 10
[unit_type_name] => Homework
[is_graded] => 1
[standard_id] => 1219
[scoring_type] => score
[attempt_score] => 8
[unit_duedate] => 2016-02-10 09:00:00
[standard] => Array
(
[0] => stdClass Object
(
[unit_id] => 6504
[is_formal] => 1
[assignment_name] => Grade assignment
[assignment_description] =>
[standard_id] => 1220
[standard_name] => 9-10.RL.3
[standard_description] => Analyze how complex characters (e.g., those with multiple or conflicting motivations) develop over the course of a
)
)
)
[1] => Array
(
[unit_id] => 8584
[assignment_name] => Sine and Cosecant Graphs
[assignment_description] => Define the sine and cosecant graphs using a unit circle
[assignment_total_score] => 15
[unit_type_name] => Paper
[scoring_type] => score
[attempt_score] => 0
[unit_duedate] => 2016-04-29 09:00:00
[standard] => Array
(
[0] => stdClass Object
(
[unit_id] => 8584
[is_formal] => 1
[assignment_name] => Sine and Cosecant Graphs
[assignment_description] => Define the sine and cosecant graphs using a unit circle
[assignment_total_score] => 15
[standard_id] => 82790
[standard_name] => 9-10.RL.7
)
)
[2] => Array
(
[unit_id] => 11611
[assignment_name] => Adding 5 + 3 + 6
[assignment_description] =>
[assignment_total_score] => 10
[unit_type_name] => Homework
[standard_id] => 82772
[scoring_type] => score
[attempt_score] => 0
[unit_duedate] => 2016-08-23 19:00:00
[standard] => Array
(
[0] => stdClass Object
(
[unit_id] => 11611
[is_formal] => 1
[assignment_name] => Adding 5 + 3 + 6
[assignment_description] =>
[assignment_total_score] => 10
[standard_id] => 82772
[standard_name] => 9-10.RL.1
)
)
)
)
我想根据每个子数组中的 unit_type_name
字段将其分组到一个新的切片中。
如何按 unit_type_name
对切片进行分组?是否有任何本机 Go 函数可用于执行此操作?
如果我循环上面的内容,那么我将得到一个重复的,我怎样才能避免这种情况?
我认为 Go 没有内置功能可以帮助你做到这一点(我可能是错的)。我的假设是 PHP 数组将转换为 JSON 对象。我设法得到下面的代码来帮助你根据 unit_type_name
对数组(JSON 格式)进行排序
我创建了两个结构,它们具有 JSON 类似于数组键的值
//StandardType ...
type StandardType struct {
UnitID int `json:"unit_id"`
IsFormal int `json:"is_formal"`
AssignmentName string `json:"assignment_name"`
AssignmentDescription string `json:"assignment_description"`
StandardID int `json:"standard_id"`
StandardName string `json:"standard_name"`
StandardDescription string `json:"standard_description"`
}
//AutoGenerated ...
type AutoGenerated struct {
UnitID int `json:"unit_id"`
AssignmentName string `json:"assignment_name"`
AssignmentDescription string `json:"assignment_description"`
AssignmentTotalScore int `json:"assignment_total_score"`
UnitTypeName string `json:"unit_type_name"`
IsGraded int `json:"is_graded"`
StandardID int `json:"standard_id"`
ScoringType string `json:"scoring_type"`
AttemptScore int `json:"attempt_score"`
UnitDuedate string `json:"unit_duedate"`
Standard []StandardType `json:"standard"`
}
var jsonData = ``
func main() {
m := []AutoGenerated{}
err := json.Unmarshal([]byte(jsonData), &m)
if err != nil {
panic(err)
}
我创建了一个地图来放置 unit_type_name
键
sliceKeys := make(map[string]string)
我还创建了映射以保存在自动生成数组中具有相似 unit_type_name
键的数组
groupedSlices := make(map[string][]AutoGenerated)
然后我遍历解码的 JSON 字符串搜索 unit_type_name
for i := range m {
如果键切片中已经存在 unit_type_name 我将数组项添加到组切片中
if _, ok := sliceKeys[m[i].UnitTypeName]; ok {
autogenerated := groupedSlices[m[i].UnitTypeName]
autogenerated = append(autogenerated, m[i])
groupedSlices[m[i].UnitTypeName] = autogenerated
} else {
否则我会创建一个新的数组键并将项目添加到其中
sliceKeys[m[i].UnitTypeName] = m[i].UnitTypeName
autogenerated := []AutoGenerated{}
autogenerated = append(autogenerated, m[i])
groupedSlices[m[i].UnitTypeName] = autogenerated
}
}
fmt.Println(sliceKeys)
fmt.Println(groupedSlices)
}
输入:
[{"unit_id": 6504,"assignment_name": "Grade assignment","assignment_description": "","assignment_total_score": 10,"unit_type_name": "Homework","is_graded": 1,"standard_id": 1219,
"scoring_type": "score","attempt_score": 8,"unit_duedate": "2016-02-10 09:00:00",
"standard": [{"unit_id": 6504,"is_formal": 1,"assignment_name": "Grade assignment","assignment_description": "",
"standard_id": 1220,"standard_name": "9-10.RL.3","standard_description": "Analyze how complex characters (e.g., those with multiple or conflicting motivations) develop over the course of a "
}]},{"unit_id": 6504,"assignment_name": "Grade assignment","assignment_description": "","assignment_total_score": 10,
"unit_type_name": "Paper","is_graded": 1,"standard_id": 1219,"scoring_type": "score","attempt_score": 8,"unit_duedate": "2016-02-10 09:00:00","standard": [{"unit_id": 6504,"is_formal": 1,"assignment_name": "Grade assignment","assignment_description": "","standard_id": 1220,"standard_name": "9-10.RL.3","standard_description": "Analyze how complex characters (e.g., those with multiple or conflicting motivations) develop over the course of a "}]},{
"unit_id": 6504,"assignment_name": "Grade assignment","assignment_description": "",
"assignment_total_score": 10,"unit_type_name": "Aything else","is_graded": 1,"standard_id": 1219,
"scoring_type": "score","attempt_score": 8,"unit_duedate": "2016-02-10 09:00:00","standard": [{
"unit_id": 6504,"is_formal": 1,"assignment_name": "Grade assignment","assignment_description": "","standard_id": 1220,
"standard_name": "9-10.RL.3","standard_description": "Analyze how complex characters (e.g., those with multiple or conflicting motivations) develop over the course of a "}]}]
输出:
map[Homework:Homework Paper:Paper Aything else:Aything else]
map[
Homework:[
{6504 Grade assignment 10 Homework 1 1219 score 8 2016-02-10 09:00:00 [{6504 1 Grade assignment 1220 9-10.RL.3 Analyze how complex characters (e.g., those with multiple or conflicting motivations) develop over the course of a }]}
]
Paper:[
{6504 Grade assignment 10 Paper 1 1219 score 8 2016-02-10 09:00:00 [{6504 1 Grade assignment 1220 9-10.RL.3 Analyze how complex characters (e.g., those with multiple or conflicting motivations) develop over the course of a }]}
]
Aything else:[
{6504 Grade assignment 10 Aything else 1 1219 score 8 2016-02-10 09:00:00 [{6504 1 Grade assignment 1220 9-10.RL.3 Analyze how complex characters (e.g., those with multiple or conflicting motivations) develop over the course of a }]}]
]
这是我写的一个通用的 GroupBy 函数:
// Created by BaiJiFeiLong@gmail.com at 2021/8/27 10:51
package main
import (
"fmt"
"reflect"
"strconv"
)
func GroupBy(arr interface{}, groupFunc interface{}) interface{} {
groupMap := reflect.MakeMap(reflect.MapOf(reflect.TypeOf(groupFunc).Out(0), reflect.TypeOf(arr)))
for i := 0; i < reflect.ValueOf(arr).Len(); i++ {
groupPivot := reflect.ValueOf(groupFunc).Call([]reflect.Value{reflect.ValueOf(arr).Index(i)})[0]
if !groupMap.MapIndex(groupPivot).IsValid() {
groupMap.SetMapIndex(groupPivot, reflect.MakeSlice(reflect.SliceOf(reflect.TypeOf(arr).Elem()), 0, 0))
}
groupMap.SetMapIndex(groupPivot, reflect.Append(groupMap.MapIndex(groupPivot), reflect.ValueOf(arr).Index(i)))
}
return groupMap.Interface()
}
func main() {
fmt.Println(GroupBy([]int{1, 22, 3, 44, 555}, func(value int) string {
return strconv.Itoa(len(strconv.Itoa(value)))
}))
}
输出:
map[1:[1 3] 2:[22 44] 3:[555]]
对于你的问题,应该是这样的代码:
group := GroupBy(items, func(item Item) string {
return item.UnitTypeName
}).(map[string][]Item)