From 93e63b1ace526018c767c24dd1c2fa75716e3c79 Mon Sep 17 00:00:00 2001 From: kercylan98 Date: Mon, 21 Aug 2023 14:40:06 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20slice=20=E5=8C=85=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E4=BC=98=E5=85=88=E7=BA=A7=E5=88=87=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- utils/slice/priority.go | 151 +++++++++++++++++++++++++++++++++++ utils/slice/priority_item.go | 34 ++++++++ utils/slice/priority_test.go | 14 ++++ 3 files changed, 199 insertions(+) create mode 100644 utils/slice/priority.go create mode 100644 utils/slice/priority_item.go create mode 100644 utils/slice/priority_test.go diff --git a/utils/slice/priority.go b/utils/slice/priority.go new file mode 100644 index 0000000..82073d9 --- /dev/null +++ b/utils/slice/priority.go @@ -0,0 +1,151 @@ +package slice + +import ( + "fmt" + "sort" +) + +// NewPriority 创建一个优先级切片 +func NewPriority[V any](lengthAndCap ...int) *Priority[V] { + p := &Priority[V]{} + if len(lengthAndCap) > 0 { + var length = lengthAndCap[0] + var c int + if len(lengthAndCap) > 1 { + c = lengthAndCap[1] + } + p.items = make([]*PriorityItem[V], length, c) + } + return p +} + +// Priority 是一个优先级切片 +type Priority[V any] struct { + items []*PriorityItem[V] +} + +// Len 返回切片长度 +func (slf *Priority[V]) Len() int { + return len(slf.items) +} + +// Cap 返回切片容量 +func (slf *Priority[V]) Cap() int { + return cap(slf.items) +} + +// Clear 清空切片 +func (slf *Priority[V]) Clear() { + clear(slf.items) +} + +// Append 添加元素 +func (slf *Priority[V]) Append(v V, priority int) { + slf.items = append(slf.items, NewPriorityItem[V](v, priority)) + slf.sort() +} + +// Appends 添加元素 +func (slf *Priority[V]) Appends(priority int, vs ...V) { + for _, v := range vs { + slf.Append(v, priority) + } + slf.sort() +} + +// Get 获取元素 +func (slf *Priority[V]) Get(index int) *PriorityItem[V] { + return slf.items[index] +} + +// GetValue 获取元素值 +func (slf *Priority[V]) GetValue(index int) V { + return slf.items[index].Value() +} + +// GetPriority 获取元素优先级 +func (slf *Priority[V]) GetPriority(index int) int { + return slf.items[index].Priority() +} + +// Set 设置元素 +func (slf *Priority[V]) Set(index int, value V, priority int) { + before := slf.items[index] + slf.items[index] = NewPriorityItem[V](value, priority) + if before.Priority() != priority { + slf.sort() + } +} + +// SetValue 设置元素值 +func (slf *Priority[V]) SetValue(index int, value V) { + slf.items[index].v = value +} + +// SetPriority 设置元素优先级 +func (slf *Priority[V]) SetPriority(index int, priority int) { + slf.items[index].p = priority + slf.sort() +} + +// Action 直接操作切片,如果返回值不为 nil,则替换切片 +func (slf *Priority[V]) Action(action func(items []*PriorityItem[V]) []*PriorityItem[V]) { + if replace := action(slf.items); replace != nil { + slf.items = replace + slf.sort() + } +} + +// Range 遍历切片,如果返回值为 false,则停止遍历 +func (slf *Priority[V]) Range(action func(index int, item *PriorityItem[V]) bool) { + for i, item := range slf.items { + if !action(i, item) { + break + } + } +} + +// RangeValue 遍历切片值,如果返回值为 false,则停止遍历 +func (slf *Priority[V]) RangeValue(action func(index int, value V) bool) { + slf.Range(func(index int, item *PriorityItem[V]) bool { + return action(index, item.Value()) + }) +} + +// RangePriority 遍历切片优先级,如果返回值为 false,则停止遍历 +func (slf *Priority[V]) RangePriority(action func(index int, priority int) bool) { + slf.Range(func(index int, item *PriorityItem[V]) bool { + return action(index, item.Priority()) + }) +} + +// String 返回切片字符串 +func (slf *Priority[V]) String() string { + var vs []V + for _, item := range slf.items { + vs = append(vs, item.Value()) + } + return fmt.Sprint(vs) +} + +// sort 排序 +func (slf *Priority[V]) sort() { + if len(slf.items) <= 1 { + return + } + sort.Slice(slf.items, func(i, j int) bool { + return slf.items[i].Priority() < slf.items[j].Priority() + }) + for i := 0; i < len(slf.items); i++ { + if i == 0 { + slf.items[i].prev = nil + slf.items[i].next = slf.items[i+1] + } else if i == len(slf.items)-1 { + slf.items[i].prev = slf.items[i-1] + slf.items[i].next = nil + } else { + slf.items[i].prev = slf.items[i-1] + slf.items[i].next = slf.items[i+1] + } + } +} diff --git a/utils/slice/priority_item.go b/utils/slice/priority_item.go new file mode 100644 index 0000000..2bccbc2 --- /dev/null +++ b/utils/slice/priority_item.go @@ -0,0 +1,34 @@ +package slice + +// NewPriorityItem 创建一个优先级切片元素 +func NewPriorityItem[V any](v V, priority int) *PriorityItem[V] { + return &PriorityItem[V]{v: v, p: priority} +} + +// PriorityItem 是一个优先级切片元素 +type PriorityItem[V any] struct { + next *PriorityItem[V] + prev *PriorityItem[V] + v V + p int +} + +// Value 返回元素值 +func (p *PriorityItem[V]) Value() V { + return p.v +} + +// Priority 返回元素优先级 +func (p *PriorityItem[V]) Priority() int { + return p.p +} + +// Next 返回下一个元素 +func (p *PriorityItem[V]) Next() *PriorityItem[V] { + return p.next +} + +// Prev 返回上一个元素 +func (p *PriorityItem[V]) Prev() *PriorityItem[V] { + return p.prev +} diff --git a/utils/slice/priority_test.go b/utils/slice/priority_test.go new file mode 100644 index 0000000..873f3bb --- /dev/null +++ b/utils/slice/priority_test.go @@ -0,0 +1,14 @@ +package slice_test + +import ( + "fmt" + "github.com/kercylan98/minotaur/utils/slice" + "testing" +) + +func TestPriority_Append(t *testing.T) { + var s = slice.NewPriority[string]() + s.Append("name_1", 2) + s.Append("name_2", 1) + fmt.Println(s) +}