diff --git a/containers/iterator.go b/containers/iterator.go index 1bd7b0e..5692982 100644 --- a/containers/iterator.go +++ b/containers/iterator.go @@ -85,21 +85,24 @@ type IteratorWithKey interface { // Prev() function to enable traversal in reverse // // Last() function to move the iterator to the last element. +// +// End() function to move the iterator past the last element (one-past-the-end). type ReverseIteratorWithIndex interface { // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. // If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. Prev() bool + // End moves the iterator past the last element (one-past-the-end). + // Call Prev() to fetch the last element if any. + End() + // Last moves the iterator to the last element and returns true if there was a last element in the container. // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. Last() bool IteratorWithIndex - // Next() bool - // Value() interface{} - // Index() int } // ReverseIteratorWithKey is a stateful iterator for ordered containers whose elements are key value pairs. @@ -115,13 +118,14 @@ type ReverseIteratorWithKey interface { // Modifies the state of the iterator. Prev() bool + // End moves the iterator past the last element (one-past-the-end). + // Call Prev() to fetch the last element if any. + End() + // Last moves the iterator to the last element and returns true if there was a last element in the container. // If Last() returns true, then last element's key and value can be retrieved by Key() and Value(). // Modifies the state of the iterator. Last() bool IteratorWithKey - // Next() bool - // Value() interface{} - // Key() interface{} } diff --git a/examples/main/iteratorwithindex.go b/examples/main/iteratorwithindex.go new file mode 100644 index 0000000..6b715d4 --- /dev/null +++ b/examples/main/iteratorwithindex.go @@ -0,0 +1,55 @@ +/* +Copyright (c) 2015, Emir Pasic +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package main + +import ( + "fmt" + "github.com/emirpasic/gods/sets/treeset" +) + +// IteratorWithIndexExample to demonstrate basic usage of IteratorWithIndex +//func IteratorWithIndexExample() { +func main() { + set := treeset.NewWithIntComparator() + set.Add(1, 2, 3) + + // Forward iteration + it := set.Iterator() + for it.Next() { + index, value := it.Index(), it.Value() + fmt.Println("Index: ", index, "Value: ", value) + } + + // Backward iteration (reverse) + for it.Last(); ; { + index, value := it.Index(), it.Value() + fmt.Println("Index: ", index, "Value: ", value) + if !it.Prev() { + break + } + } +} diff --git a/lists/arraylist/arraylist.go b/lists/arraylist/arraylist.go index 57eca3c..4e44d4a 100644 --- a/lists/arraylist/arraylist.go +++ b/lists/arraylist/arraylist.go @@ -230,6 +230,12 @@ func (iterator *Iterator) Begin() { iterator.index = -1 } +// End moves the iterator past the last element (one-past-the-end). +// Call Prev() to fetch the last element if any. +func (iterator *Iterator) End() { + iterator.index = iterator.list.size +} + // First moves the iterator to the first element and returns true if there was a first element in the container. // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. @@ -242,7 +248,7 @@ func (iterator *Iterator) First() bool { // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. func (iterator *Iterator) Last() bool { - iterator.index = iterator.list.size + iterator.End() return iterator.Prev() } diff --git a/lists/doublylinkedlist/doublylinkedlist.go b/lists/doublylinkedlist/doublylinkedlist.go index 2f5bb2e..184db76 100644 --- a/lists/doublylinkedlist/doublylinkedlist.go +++ b/lists/doublylinkedlist/doublylinkedlist.go @@ -370,6 +370,13 @@ func (iterator *Iterator) Begin() { iterator.element = nil } +// End moves the iterator past the last element (one-past-the-end). +// Call Prev() to fetch the last element if any. +func (iterator *Iterator) End() { + iterator.index = iterator.list.size + iterator.element = iterator.list.last +} + // First moves the iterator to the first element and returns true if there was a first element in the container. // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. @@ -382,8 +389,7 @@ func (iterator *Iterator) First() bool { // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. func (iterator *Iterator) Last() bool { - iterator.index = iterator.list.size - iterator.element = iterator.list.last + iterator.End() return iterator.Prev() } diff --git a/maps/treemap/treemap.go b/maps/treemap/treemap.go index 1b531ee..995d25b 100644 --- a/maps/treemap/treemap.go +++ b/maps/treemap/treemap.go @@ -171,12 +171,17 @@ func (iterator *Iterator) Begin() { iterator.iterator.Begin() } +// End moves the iterator past the last element (one-past-the-end). +// Call Prev() to fetch the last element if any. +func (iterator *Iterator) End() { + iterator.iterator.End() +} + // First moves the iterator to the first element and returns true if there was a first element in the container. // If First() returns true, then first element's key and value can be retrieved by Key() and Value(). // Modifies the state of the iterator func (iterator *Iterator) First() bool { - iterator.Begin() - return iterator.Next() + return iterator.iterator.First() } // Last moves the iterator to the last element and returns true if there was a last element in the container. diff --git a/sets/treeset/treeset.go b/sets/treeset/treeset.go index 8acd804..6651bae 100644 --- a/sets/treeset/treeset.go +++ b/sets/treeset/treeset.go @@ -158,6 +158,13 @@ func (iterator *Iterator) Begin() { iterator.iterator.Begin() } +// End moves the iterator past the last element (one-past-the-end). +// Call Prev() to fetch the last element if any. +func (iterator *Iterator) End() { + iterator.index = iterator.tree.Size() + iterator.iterator.End() +} + // First moves the iterator to the first element and returns true if there was a first element in the container. // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. @@ -170,7 +177,7 @@ func (iterator *Iterator) First() bool { // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. func (iterator *Iterator) Last() bool { - iterator.index = iterator.tree.Size() + iterator.End() return iterator.iterator.Last() } diff --git a/stacks/arraystack/arraystack.go b/stacks/arraystack/arraystack.go index 81f6837..ee7cc82 100644 --- a/stacks/arraystack/arraystack.go +++ b/stacks/arraystack/arraystack.go @@ -149,6 +149,12 @@ func (iterator *Iterator) Begin() { iterator.index = -1 } +// End moves the iterator past the last element (one-past-the-end). +// Call Prev() to fetch the last element if any. +func (iterator *Iterator) End() { + iterator.index = iterator.stack.Size() +} + // First moves the iterator to the first element and returns true if there was a first element in the container. // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. @@ -161,7 +167,7 @@ func (iterator *Iterator) First() bool { // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. func (iterator *Iterator) Last() bool { - iterator.index = iterator.stack.Size() + iterator.End() return iterator.Prev() } diff --git a/trees/binaryheap/binaryheap.go b/trees/binaryheap/binaryheap.go index fc62d79..4845c31 100644 --- a/trees/binaryheap/binaryheap.go +++ b/trees/binaryheap/binaryheap.go @@ -165,6 +165,12 @@ func (iterator *Iterator) Begin() { iterator.index = -1 } +// End moves the iterator past the last element (one-past-the-end). +// Call Prev() to fetch the last element if any. +func (iterator *Iterator) End() { + iterator.index = iterator.heap.Size() +} + // First moves the iterator to the first element and returns true if there was a first element in the container. // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. @@ -177,7 +183,7 @@ func (iterator *Iterator) First() bool { // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). // Modifies the state of the iterator. func (iterator *Iterator) Last() bool { - iterator.index = iterator.heap.Size() + iterator.End() return iterator.Prev() } diff --git a/trees/redblacktree/redblacktree.go b/trees/redblacktree/redblacktree.go index 134c74e..323cfac 100644 --- a/trees/redblacktree/redblacktree.go +++ b/trees/redblacktree/redblacktree.go @@ -363,6 +363,13 @@ func (iterator *Iterator) Begin() { iterator.node = nil } +// End moves the iterator past the last element (one-past-the-end). +// Call Prev() to fetch the last element if any. +func (iterator *Iterator) End() { + right := iterator.tree.Right() // ugly hack (TODO: use flags) + iterator.node = &Node{Parent: right, Key: right.Key} +} + // First moves the iterator to the first element and returns true if there was a first element in the container. // If First() returns true, then first element's key and value can be retrieved by Key() and Value(). // Modifies the state of the iterator @@ -375,8 +382,8 @@ func (iterator *Iterator) First() bool { // If Last() returns true, then last element's key and value can be retrieved by Key() and Value(). // Modifies the state of the iterator. func (iterator *Iterator) Last() bool { - iterator.node = iterator.tree.Right() - return iterator.node != nil + iterator.End() + return iterator.Prev() } // String returns a string representation of container