diff --git a/tree/tree.go b/tree/tree.go index 747e778..aa52839 100644 --- a/tree/tree.go +++ b/tree/tree.go @@ -4,17 +4,7 @@ import ( "cmp" ) -type NodeSlice[I cmp.Ordered, E any] []NodeTree[I, E] -func (nodes NodeSlice[T, E]) Len() int { - return len(nodes) -} -func (nodes NodeSlice[T, E]) Less(i, j int) bool { - return nodes[i].GetId() < nodes[j].GetId() -} -func (nodes NodeSlice[T, E]) Swap(i, j int) { - nodes[i], nodes[j] = nodes[j], nodes[i] -} type NodeTree[I cmp.Ordered, T any] interface { GetId() I @@ -27,39 +17,37 @@ type Node[I cmp.Ordered, U NodeTree[I, U]] interface { MapTree() U } -// IntoTree 列表转树, 切片无children, map转换 +// IntoTree 列表转树, 切片无children // 两次循环就可以获取列表转树 func IntoTree[I cmp.Ordered, E Node[I, U], U NodeTree[I, U]](rows []E, rootPid I) []U { nodes := make([]U, 0, len(rows)) nodeMaps := make(map[I]U) for _, v := range rows { - vv := v.MapTree() - nodes = append(nodes, vv) - nodeMaps[v.MapId()] = vv + e := v.MapTree() + nodes = append(nodes, e) + nodeMaps[v.MapId()] = e } return intoTree(nodeMaps, nodes, rootPid) } -// IntoTree 列表转树 +// IntoTree 列表转树, 切片有children // 两次循环就可以获取列表转树 func IntoTree2[T cmp.Ordered, E NodeTree[T, E]](rows []E, rootPid T) []E { nodeMaps := make(map[T]E) - for _, v := range rows { - vv := v - nodeMaps[v.GetId()] = vv + for _, e := range rows { + nodeMaps[e.GetId()] = e } return intoTree(nodeMaps, rows, rootPid) } func intoTree[T cmp.Ordered, E NodeTree[T, E]](nodeMaps map[T]E, rows []E, rootPid T) []E { var root []E - for _, v := range rows { - node := v - pid := node.GetPid() + for _, e := range rows { + pid := e.GetPid() if pid == rootPid { - root = append(root, node) + root = append(root, e) } else if parent, exists := nodeMaps[pid]; exists { - parent.AppendChildren(node) + parent.AppendChildren(e) } } return root diff --git a/tree/tree_sort.go b/tree/tree_sort.go new file mode 100644 index 0000000..ab633fc --- /dev/null +++ b/tree/tree_sort.go @@ -0,0 +1,15 @@ +package tree + +import "cmp" + +type NodeSlice[I cmp.Ordered, E any] []NodeTree[I, E] + +func (nodes NodeSlice[T, E]) Len() int { + return len(nodes) +} +func (nodes NodeSlice[T, E]) Less(i, j int) bool { + return nodes[i].GetId() < nodes[j].GetId() +} +func (nodes NodeSlice[T, E]) Swap(i, j int) { + nodes[i], nodes[j] = nodes[j], nodes[i] +} diff --git a/tree/tree_test.go b/tree/tree_test.go index 2644f98..fef312b 100644 --- a/tree/tree_test.go +++ b/tree/tree_test.go @@ -7,13 +7,19 @@ import ( "github.com/stretchr/testify/require" ) +var _ Node[int, *DeptTree] = (*Dept)(nil) +var _ NodeTree[int, *DeptTree] = (*DeptTree)(nil) + type Dept struct { Id int Pid int Name string } +// MapId implements Node. func (d *Dept) MapId() int { return d.Id } + +// MapTree implements Node. func (d *Dept) MapTree() *DeptTree { return &DeptTree{ Dept: d, @@ -26,9 +32,13 @@ type DeptTree struct { Children []*DeptTree } -func (d *DeptTree) GetId() int { return d.Id } +// GetId implements NodeTree. +func (d *DeptTree) GetId() int { return d.Id } + +// GetPid implements NodeTree. func (d *DeptTree) GetPid() int { return d.Pid } +// AppendChildren implements NodeTree. func (d *DeptTree) AppendChildren(v *DeptTree) { d.Children = append(d.Children, v) } @@ -48,8 +58,19 @@ var arr = []*Dept{ } func TestTree(t *testing.T) { - vv := IntoTree(arr, 0) - v, err := json.MarshalIndent(vv, " ", " ") + gotTree1 := IntoTree(arr, 0) + tree1, err := json.MarshalIndent(gotTree1, " ", " ") + require.NoError(t, err) + + arrTree := make([]*DeptTree, 0, len(arr)) + for _, v := range arr { + vv := *v + arrTree = append(arrTree, vv.MapTree()) + } + + gotTree2 := IntoTree2(arrTree, 0) + tree2, err := json.MarshalIndent(gotTree2, " ", " ") require.NoError(t, err) - t.Log(string(v)) + + require.Equal(t, tree2, tree1) }