| package treex |
|
|
| import ( |
| "errors" |
| "reflect" |
|
|
| "github.com/samber/lo" |
| ) |
|
|
| func NewNode[T any](value T) *Node[T] { |
| if reflect.ValueOf(value).Kind() != reflect.Pointer { |
| panic("Node value has to be a pointer") |
| } |
|
|
| if reflect.ValueOf(value).IsNil() { |
| panic("Node value has to be a non-nil pointer") |
| } |
|
|
| return &Node[T]{value: value} |
| } |
|
|
| type Node[T any] struct { |
| value T |
| parent *Node[T] |
| children []*Node[T] |
| } |
|
|
| |
| |
| |
| |
| |
| func (n *Node[T]) ShallowClone() *Node[T] { |
| children := make([]*Node[T], len(n.children)) |
| copy(children, n.children) |
|
|
| clone := &Node[T]{ |
| value: n.value, |
| parent: n.parent, |
| children: children, |
| } |
|
|
| for _, child := range children { |
| if child != nil { |
| child.parent = clone |
| } |
| } |
|
|
| return clone |
| } |
|
|
| |
| |
| |
| func (n *Node[T]) DeepClone() *Node[T] { |
| if n == nil { |
| return nil |
| } |
|
|
| |
| clone := &Node[T]{ |
| value: n.value, |
| parent: nil, |
| } |
| |
| for _, child := range n.children { |
| if child == nil { |
| continue |
| } |
| childClone := child.DeepClone() |
| clone.AddChild(childClone) |
| } |
| return clone |
| } |
|
|
| func (n *Node[T]) SetValue(value T) { |
| n.value = value |
| } |
|
|
| func (n *Node[T]) Value() T { |
| return n.value |
| } |
|
|
| func (n *Node[T]) Parent() *Node[T] { |
| return n.parent |
| } |
|
|
| func (n *Node[T]) Children() []*Node[T] { |
| return n.children |
| } |
|
|
| func (n *Node[T]) AddChild(child *Node[T]) { |
| n.children = append(n.children, child) |
| child.parent = n |
| } |
|
|
| func (n *Node[T]) RemoveChild(child *Node[T]) error { |
| _, ok := lo.Find(n.children, func(c *Node[T]) bool { |
| return c == child |
| }) |
|
|
| if !ok { |
| return errors.New("child not found") |
| } |
|
|
| n.children = lo.Filter(n.children, func(c *Node[T], _ int) bool { |
| return c != child |
| }) |
|
|
| child.parent = nil |
|
|
| return nil |
| } |
|
|
| func (n *Node[T]) SwapChild(old *Node[T], new *Node[T]) error { |
| _, idx, ok := lo.FindIndexOf(n.children, func(c *Node[T]) bool { |
| return c == old |
| }) |
|
|
| if !ok { |
| return errors.New("child not found") |
| } |
|
|
| n.children[idx] = new |
| old.parent = nil |
| new.parent = n |
|
|
| return nil |
| } |
|
|
| func (n *Node[T]) IsLeaf() bool { |
| return len(n.children) == 0 |
| } |
|
|
| func (n *Node[T]) IsRoot() bool { |
| return n.parent == nil |
| } |
|
|