| package sets |
|
|
| import ( |
| "encoding/json" |
| "iter" |
| "slices" |
|
|
| "github.com/elliotchance/orderedmap/v3" |
| ) |
|
|
| var ( |
| _ json.Marshaler = (*OrderedSet[int, any])(nil) |
| _ json.Unmarshaler = (*OrderedSet[int, any])(nil) |
| ) |
|
|
| type OrderedSet[K comparable, V any] struct { |
| h func(V) K |
| m *orderedmap.OrderedMap[K, V] |
| } |
|
|
| func NewOrderedSet[T comparable]() *OrderedSet[T, T] { |
| return &OrderedSet[T, T]{ |
| h: func(t T) T { return t }, |
| m: orderedmap.NewOrderedMap[T, T](), |
| } |
| } |
|
|
| func NewOrderedSetWithHash[K comparable, V any](hash func(V) K) *OrderedSet[K, V] { |
| return &OrderedSet[K, V]{ |
| h: hash, |
| m: orderedmap.NewOrderedMap[K, V](), |
| } |
| } |
|
|
| func (s *OrderedSet[K, V]) Len() int { |
| return s.m.Len() |
| } |
|
|
| func (s *OrderedSet[K, V]) Add(items ...V) { |
| for _, result := range items { |
| s.m.Set(s.h(result), result) |
| } |
| } |
|
|
| func (s *OrderedSet[K, V]) Del(items ...V) { |
| for _, result := range items { |
| s.m.Delete(s.h(result)) |
| } |
| } |
|
|
| func (s *OrderedSet[K, V]) Iterator() iter.Seq[V] { |
| return func(yield func(V) bool) { |
| for _, v := range s.m.AllFromFront() { |
| if !yield(v) { |
| return |
| } |
| } |
| } |
| } |
|
|
| func (s *OrderedSet[K, V]) AsSlice() []V { |
| return slices.Collect(s.Iterator()) |
| } |
|
|
| func (s *OrderedSet[K, V]) MarshalJSON() ([]byte, error) { |
| return json.Marshal(s.AsSlice()) |
| } |
|
|
| func (s *OrderedSet[K, V]) UnmarshalJSON(data []byte) error { |
| vs := make([]V, 0) |
| if err := json.Unmarshal(data, &vs); err != nil { |
| return err |
| } |
| s.Add(vs...) |
| return nil |
| } |
|
|