list.gno

7.11 Kb ยท 331 lines
  1// Package list implements a dynamic list data structure backed by an AVL tree.
  2// It provides O(log n) operations for most list operations while maintaining
  3// order stability.
  4//
  5// The list supports various operations including append, get, set, delete,
  6// range queries, and iteration. It can store values of any type.
  7//
  8// Example usage:
  9//
 10//	// Create a new list and add elements
 11//	var l list.List
 12//	l.Append(1, 2, 3)
 13//
 14//	// Get and set elements
 15//	value := l.Get(1)  // returns 2
 16//	l.Set(1, 42)      // updates index 1 to 42
 17//
 18//	// Delete elements
 19//	l.Delete(0)       // removes first element
 20//
 21//	// Iterate over elements
 22//	l.ForEach(func(index int, value any) bool {
 23//	    ufmt.Printf("index %d: %v\n", index, value)
 24//	    return false  // continue iteration
 25//	})
 26//	// Output:
 27//	// index 0: 42
 28//	// index 1: 3
 29//
 30//	// Create a list of specific size
 31//	l = list.Make(3, "default")  // creates [default, default, default]
 32//
 33//	// Create a list using a variable declaration
 34//	var l2 list.List
 35//	l2.Append(4, 5, 6)
 36//	println(l2.Len())  // Output: 3
 37package list
 38
 39import (
 40	"gno.land/p/nt/avl"
 41	"gno.land/p/nt/avl/rotree"
 42	"gno.land/p/nt/seqid"
 43)
 44
 45// IList defines the interface for list operations
 46type IList interface {
 47	Len() int
 48	Append(values ...any)
 49	Get(index int) any
 50	Set(index int, value any) bool
 51	Delete(index int) (any, bool)
 52	Slice(startIndex, endIndex int) []any
 53	ForEach(fn func(index int, value any) bool)
 54	Clone() *List
 55	DeleteRange(startIndex, endIndex int) int
 56}
 57
 58// Verify List implements IList interface
 59var _ IList = (*List)(nil)
 60
 61// List represents an ordered sequence of items backed by an AVL tree
 62type List struct {
 63	tree  avl.Tree
 64	idGen seqid.ID
 65}
 66
 67// Len returns the number of elements in the list.
 68//
 69// Example:
 70//
 71//	var l list.List
 72//	l.Append(1, 2, 3)
 73//	println(l.Len()) // Output: 3
 74func (l *List) Len() int {
 75	return l.tree.Size()
 76}
 77
 78// Append adds one or more values to the end of the list.
 79//
 80// Example:
 81//
 82//	var l list.List
 83//	l.Append(1)        // adds single value
 84//	l.Append(2, 3, 4)  // adds multiple values
 85//	println(l.Len()) // Output: 4
 86func (l *List) Append(values ...any) {
 87	for _, v := range values {
 88		l.tree.Set(l.idGen.Next().String(), v)
 89	}
 90}
 91
 92// Get returns the value at the specified index.
 93// Returns nil if index is out of bounds.
 94//
 95// Example:
 96//
 97//	var l list.List
 98//	l.Append(1, 2, 3)
 99//	println(l.Get(1))    // Output: 2
100//	println(l.Get(-1))   // Output: nil
101//	println(l.Get(999))  // Output: nil
102func (l *List) Get(index int) any {
103	if index < 0 || index >= l.tree.Size() {
104		return nil
105	}
106	_, value := l.tree.GetByIndex(index)
107	return value
108}
109
110// Set updates or appends a value at the specified index.
111// Returns true if the operation was successful, false otherwise.
112// For empty lists, only index 0 is valid (append case).
113//
114// Example:
115//
116//	var l list.List
117//	l.Append(1, 2, 3)
118//
119//	l.Set(1, 42)      // updates existing index
120//	println(l.Get(1)) // Output: 42
121//
122//	l.Set(3, 4)       // appends at end
123//	println(l.Get(3)) // Output: 4
124//
125//	l.Set(-1, 5)      // invalid index
126//	println(l.Len()) // Output: 4 (list unchanged)
127func (l *List) Set(index int, value any) bool {
128	size := l.tree.Size()
129
130	// Handle empty list case - only allow index 0
131	if size == 0 {
132		if index == 0 {
133			l.Append(value)
134			return true
135		}
136		return false
137	}
138
139	if index < 0 || index > size {
140		return false
141	}
142
143	// If setting at the end (append case)
144	if index == size {
145		l.Append(value)
146		return true
147	}
148
149	// Get the key at the specified index
150	key, _ := l.tree.GetByIndex(index)
151	if key == "" {
152		return false
153	}
154
155	// Update the value at the existing key
156	l.tree.Set(key, value)
157	return true
158}
159
160// Delete removes the element at the specified index.
161// Returns the deleted value and true if successful, nil and false otherwise.
162//
163// Example:
164//
165//	var l list.List
166//	l.Append(1, 2, 3)
167//
168//	val, ok := l.Delete(1)
169//	println(val, ok)  // Output: 2 true
170//	println(l.Len())  // Output: 2
171//
172//	val, ok = l.Delete(-1)
173//	println(val, ok)  // Output: nil false
174func (l *List) Delete(index int) (any, bool) {
175	size := l.tree.Size()
176	// Always return nil, false for empty list
177	if size == 0 {
178		return nil, false
179	}
180
181	if index < 0 || index >= size {
182		return nil, false
183	}
184
185	key, value := l.tree.GetByIndex(index)
186	if key == "" {
187		return nil, false
188	}
189
190	l.tree.Remove(key)
191	return value, true
192}
193
194// Slice returns a slice of values from startIndex (inclusive) to endIndex (exclusive).
195// Returns nil if the range is invalid.
196//
197// Example:
198//
199//	var l list.List
200//	l.Append(1, 2, 3, 4, 5)
201//
202//	println(l.Slice(1, 4))   // Output: [2 3 4]
203//	println(l.Slice(-1, 2))  // Output: [1 2]
204//	println(l.Slice(3, 999)) // Output: [4 5]
205//	println(l.Slice(3, 2))   // Output: nil
206func (l *List) Slice(startIndex, endIndex int) []any {
207	size := l.tree.Size()
208
209	// Normalize bounds
210	if startIndex < 0 {
211		startIndex = 0
212	}
213	if endIndex > size {
214		endIndex = size
215	}
216	if startIndex >= endIndex {
217		return nil
218	}
219
220	count := endIndex - startIndex
221	result := make([]any, count)
222
223	i := 0
224	l.tree.IterateByOffset(startIndex, count, func(_ string, value any) bool {
225		result[i] = value
226		i++
227		return false
228	})
229	return result
230}
231
232// ForEach iterates through all elements in the list.
233func (l *List) ForEach(fn func(index int, value any) bool) {
234	if l.tree.Size() == 0 {
235		return
236	}
237
238	index := 0
239	l.tree.IterateByOffset(0, l.tree.Size(), func(_ string, value any) bool {
240		result := fn(index, value)
241		index++
242		return result
243	})
244}
245
246// Clone creates a shallow copy of the list.
247//
248// Example:
249//
250//	var l list.List
251//	l.Append(1, 2, 3)
252//
253//	clone := l.Clone()
254//	clone.Set(0, 42)
255//
256//	println(l.Get(0))    // Output: 1
257//	println(clone.Get(0)) // Output: 42
258func (l *List) Clone() *List {
259	newList := &List{
260		tree:  avl.Tree{},
261		idGen: l.idGen,
262	}
263
264	size := l.tree.Size()
265	if size == 0 {
266		return newList
267	}
268
269	l.tree.IterateByOffset(0, size, func(_ string, value any) bool {
270		newList.Append(value)
271		return false
272	})
273
274	return newList
275}
276
277// DeleteRange removes elements from startIndex (inclusive) to endIndex (exclusive).
278// Returns the number of elements deleted.
279//
280// Example:
281//
282//	var l list.List
283//	l.Append(1, 2, 3, 4, 5)
284//
285//	deleted := l.DeleteRange(1, 4)
286//	println(deleted)     // Output: 3
287//	println(l.Range(0, l.Len())) // Output: [1 5]
288func (l *List) DeleteRange(startIndex, endIndex int) int {
289	size := l.tree.Size()
290
291	// Normalize bounds
292	if startIndex < 0 {
293		startIndex = 0
294	}
295	if endIndex > size {
296		endIndex = size
297	}
298	if startIndex >= endIndex {
299		return 0
300	}
301
302	// Collect keys to delete
303	keysToDelete := make([]string, 0, endIndex-startIndex)
304	l.tree.IterateByOffset(startIndex, endIndex-startIndex, func(key string, _ any) bool {
305		keysToDelete = append(keysToDelete, key)
306		return false
307	})
308
309	// Delete collected keys
310	for _, key := range keysToDelete {
311		l.tree.Remove(key)
312	}
313
314	return len(keysToDelete)
315}
316
317// Tree returns a read-only pointer to the underlying AVL tree.
318//
319// Example:
320//
321//	var l list.List
322//	l.Append(1, 2, 3)
323//
324//	rotree := l.Tree()
325//	rotree.ReverseIterateByOffset(0, rotree.Size(), func(key string, value any) bool {
326//	  println(value) // Output: 3 2 1
327//	  return false
328//	})
329func (l *List) Tree() *rotree.ReadOnlyTree {
330	return rotree.Wrap(&l.tree, nil)
331}