list.gno
6.72 Kb ยท 314 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/demo/avl"
41 "gno.land/p/demo/seqid"
42)
43
44// IList defines the interface for list operations
45type IList interface {
46 Len() int
47 Append(values ...any)
48 Get(index int) any
49 Set(index int, value any) bool
50 Delete(index int) (any, bool)
51 Slice(startIndex, endIndex int) []any
52 ForEach(fn func(index int, value any) bool)
53 Clone() *List
54 DeleteRange(startIndex, endIndex int) int
55}
56
57// Verify List implements IList interface
58var _ IList = (*List)(nil)
59
60// List represents an ordered sequence of items backed by an AVL tree
61type List struct {
62 tree avl.Tree
63 idGen seqid.ID
64}
65
66// Len returns the number of elements in the list.
67//
68// Example:
69//
70// l := list.New()
71// l.Append(1, 2, 3)
72// println(l.Len()) // Output: 3
73func (l *List) Len() int {
74 return l.tree.Size()
75}
76
77// Append adds one or more values to the end of the list.
78//
79// Example:
80//
81// l := list.New()
82// l.Append(1) // adds single value
83// l.Append(2, 3, 4) // adds multiple values
84// println(l.Len()) // Output: 4
85func (l *List) Append(values ...any) {
86 for _, v := range values {
87 l.tree.Set(l.idGen.Next().String(), v)
88 }
89}
90
91// Get returns the value at the specified index.
92// Returns nil if index is out of bounds.
93//
94// Example:
95//
96// l := list.New()
97// l.Append(1, 2, 3)
98// println(l.Get(1)) // Output: 2
99// println(l.Get(-1)) // Output: nil
100// println(l.Get(999)) // Output: nil
101func (l *List) Get(index int) any {
102 if index < 0 || index >= l.tree.Size() {
103 return nil
104 }
105 _, value := l.tree.GetByIndex(index)
106 return value
107}
108
109// Set updates or appends a value at the specified index.
110// Returns true if the operation was successful, false otherwise.
111// For empty lists, only index 0 is valid (append case).
112//
113// Example:
114//
115// l := list.New()
116// l.Append(1, 2, 3)
117//
118// l.Set(1, 42) // updates existing index
119// println(l.Get(1)) // Output: 42
120//
121// l.Set(3, 4) // appends at end
122// println(l.Get(3)) // Output: 4
123//
124// l.Set(-1, 5) // invalid index
125// println(l.Len()) // Output: 4 (list unchanged)
126func (l *List) Set(index int, value any) bool {
127 size := l.tree.Size()
128
129 // Handle empty list case - only allow index 0
130 if size == 0 {
131 if index == 0 {
132 l.Append(value)
133 return true
134 }
135 return false
136 }
137
138 if index < 0 || index > size {
139 return false
140 }
141
142 // If setting at the end (append case)
143 if index == size {
144 l.Append(value)
145 return true
146 }
147
148 // Get the key at the specified index
149 key, _ := l.tree.GetByIndex(index)
150 if key == "" {
151 return false
152 }
153
154 // Update the value at the existing key
155 l.tree.Set(key, value)
156 return true
157}
158
159// Delete removes the element at the specified index.
160// Returns the deleted value and true if successful, nil and false otherwise.
161//
162// Example:
163//
164// l := list.New()
165// l.Append(1, 2, 3)
166//
167// val, ok := l.Delete(1)
168// println(val, ok) // Output: 2 true
169// println(l.Len()) // Output: 2
170//
171// val, ok = l.Delete(-1)
172// println(val, ok) // Output: nil false
173func (l *List) Delete(index int) (any, bool) {
174 size := l.tree.Size()
175 // Always return nil, false for empty list
176 if size == 0 {
177 return nil, false
178 }
179
180 if index < 0 || index >= size {
181 return nil, false
182 }
183
184 key, value := l.tree.GetByIndex(index)
185 if key == "" {
186 return nil, false
187 }
188
189 l.tree.Remove(key)
190 return value, true
191}
192
193// Slice returns a slice of values from startIndex (inclusive) to endIndex (exclusive).
194// Returns nil if the range is invalid.
195//
196// Example:
197//
198// l := list.New()
199// l.Append(1, 2, 3, 4, 5)
200//
201// println(l.Slice(1, 4)) // Output: [2 3 4]
202// println(l.Slice(-1, 2)) // Output: [1 2]
203// println(l.Slice(3, 999)) // Output: [4 5]
204// println(l.Slice(3, 2)) // Output: nil
205func (l *List) Slice(startIndex, endIndex int) []any {
206 size := l.tree.Size()
207
208 // Normalize bounds
209 if startIndex < 0 {
210 startIndex = 0
211 }
212 if endIndex > size {
213 endIndex = size
214 }
215 if startIndex >= endIndex {
216 return nil
217 }
218
219 count := endIndex - startIndex
220 result := make([]any, count)
221
222 i := 0
223 l.tree.IterateByOffset(startIndex, count, func(_ string, value any) bool {
224 result[i] = value
225 i++
226 return false
227 })
228 return result
229}
230
231// ForEach iterates through all elements in the list.
232func (l *List) ForEach(fn func(index int, value any) bool) {
233 if l.tree.Size() == 0 {
234 return
235 }
236
237 index := 0
238 l.tree.IterateByOffset(0, l.tree.Size(), func(_ string, value any) bool {
239 result := fn(index, value)
240 index++
241 return result
242 })
243}
244
245// Clone creates a shallow copy of the list.
246//
247// Example:
248//
249// l := list.New()
250// l.Append(1, 2, 3)
251//
252// clone := l.Clone()
253// clone.Set(0, 42)
254//
255// println(l.Get(0)) // Output: 1
256// println(clone.Get(0)) // Output: 42
257func (l *List) Clone() *List {
258 newList := &List{
259 tree: avl.Tree{},
260 idGen: l.idGen,
261 }
262
263 size := l.tree.Size()
264 if size == 0 {
265 return newList
266 }
267
268 l.tree.IterateByOffset(0, size, func(_ string, value any) bool {
269 newList.Append(value)
270 return false
271 })
272
273 return newList
274}
275
276// DeleteRange removes elements from startIndex (inclusive) to endIndex (exclusive).
277// Returns the number of elements deleted.
278//
279// Example:
280//
281// l := list.New()
282// l.Append(1, 2, 3, 4, 5)
283//
284// deleted := l.DeleteRange(1, 4)
285// println(deleted) // Output: 3
286// println(l.Range(0, l.Len())) // Output: [1 5]
287func (l *List) DeleteRange(startIndex, endIndex int) int {
288 size := l.tree.Size()
289
290 // Normalize bounds
291 if startIndex < 0 {
292 startIndex = 0
293 }
294 if endIndex > size {
295 endIndex = size
296 }
297 if startIndex >= endIndex {
298 return 0
299 }
300
301 // Collect keys to delete
302 keysToDelete := make([]string, 0, endIndex-startIndex)
303 l.tree.IterateByOffset(startIndex, endIndex-startIndex, func(key string, _ any) bool {
304 keysToDelete = append(keysToDelete, key)
305 return false
306 })
307
308 // Delete collected keys
309 for _, key := range keysToDelete {
310 l.tree.Remove(key)
311 }
312
313 return len(keysToDelete)
314}