-
Notifications
You must be signed in to change notification settings - Fork 66
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Iterators were introduced in Go 1.23. They allow `for` loops over custom sequences. There are some breaking changes to the API, which is why it's being releases as v3. Notable changes are: - `All()` no longer exists. You can use the now native: `maps.Collect(m.AllFromFront())` for elements, or `slices.Collect(m.Keys())` for keys. - `Iterator()` and `ReverseIterator()` are now `AllFromFront()` and `AllFromBack()` respectively. - `Keys()` now returns an `iter.Seq` iterator instead of a list of keys. This should be much more performant on large maps. It is also more consistent with `maps.Keys` from the standard library. - Added `Values()` which returns an `iter.Seq` iterator. It is also consistent with `maps.Values` from the standard library. Fixes #44
- Loading branch information
Showing
7 changed files
with
1,379 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
module github.com/elliotchance/orderedmap/v3 | ||
|
||
go 1.23.0 | ||
|
||
require github.com/stretchr/testify v1.7.1 | ||
|
||
require ( | ||
github.com/davecgh/go-spew v1.1.0 // indirect | ||
github.com/pmezard/go-difflib v1.0.0 // indirect | ||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= | ||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= | ||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= | ||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
package orderedmap | ||
|
||
// Element is an element of a null terminated (non circular) intrusive doubly linked list that contains the key of the correspondent element in the ordered map too. | ||
type Element[K comparable, V any] struct { | ||
// Next and previous pointers in the doubly-linked list of elements. | ||
// To simplify the implementation, internally a list l is implemented | ||
// as a ring, such that &l.root is both the next element of the last | ||
// list element (l.Back()) and the previous element of the first list | ||
// element (l.Front()). | ||
next, prev *Element[K, V] | ||
|
||
// The key that corresponds to this element in the ordered map. | ||
Key K | ||
|
||
// The value stored with this element. | ||
Value V | ||
} | ||
|
||
// Next returns the next list element or nil. | ||
func (e *Element[K, V]) Next() *Element[K, V] { | ||
return e.next | ||
} | ||
|
||
// Prev returns the previous list element or nil. | ||
func (e *Element[K, V]) Prev() *Element[K, V] { | ||
return e.prev | ||
} | ||
|
||
// list represents a null terminated (non circular) intrusive doubly linked list. | ||
// The list is immediately usable after instantiation without the need of a dedicated initialization. | ||
type list[K comparable, V any] struct { | ||
root Element[K, V] // list head and tail | ||
} | ||
|
||
func (l *list[K, V]) IsEmpty() bool { | ||
return l.root.next == nil | ||
} | ||
|
||
// Front returns the first element of list l or nil if the list is empty. | ||
func (l *list[K, V]) Front() *Element[K, V] { | ||
return l.root.next | ||
} | ||
|
||
// Back returns the last element of list l or nil if the list is empty. | ||
func (l *list[K, V]) Back() *Element[K, V] { | ||
return l.root.prev | ||
} | ||
|
||
// Remove removes e from its list | ||
func (l *list[K, V]) Remove(e *Element[K, V]) { | ||
if e.prev == nil { | ||
l.root.next = e.next | ||
} else { | ||
e.prev.next = e.next | ||
} | ||
if e.next == nil { | ||
l.root.prev = e.prev | ||
} else { | ||
e.next.prev = e.prev | ||
} | ||
e.next = nil // avoid memory leaks | ||
e.prev = nil // avoid memory leaks | ||
} | ||
|
||
// PushFront inserts a new element e with value v at the front of list l and returns e. | ||
func (l *list[K, V]) PushFront(key K, value V) *Element[K, V] { | ||
e := &Element[K, V]{Key: key, Value: value} | ||
if l.root.next == nil { | ||
// It's the first element | ||
l.root.next = e | ||
l.root.prev = e | ||
return e | ||
} | ||
|
||
e.next = l.root.next | ||
l.root.next.prev = e | ||
l.root.next = e | ||
return e | ||
} | ||
|
||
// PushBack inserts a new element e with value v at the back of list l and returns e. | ||
func (l *list[K, V]) PushBack(key K, value V) *Element[K, V] { | ||
e := &Element[K, V]{Key: key, Value: value} | ||
if l.root.prev == nil { | ||
// It's the first element | ||
l.root.next = e | ||
l.root.prev = e | ||
return e | ||
} | ||
|
||
e.prev = l.root.prev | ||
l.root.prev.next = e | ||
l.root.prev = e | ||
return e | ||
} |
Oops, something went wrong.