Implement NextTo and PrevTo for all iterators and containers (index or key, forward-only or reversable)

This commit is contained in:
Emir Pasic
2022-04-12 01:20:56 +02:00
parent 4209f34363
commit 08ae493e8a
32 changed files with 1889 additions and 13 deletions
+107
View File
@@ -6,6 +6,7 @@ package arraystack
import (
"fmt"
"strings"
"testing"
)
@@ -232,6 +233,112 @@ func TestStackIteratorLast(t *testing.T) {
}
}
func TestStackIteratorNextTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index int, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
}
// NextTo (empty)
{
stack := New()
it := stack.Iterator()
for it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty stack")
}
}
// NextTo (not found)
{
stack := New()
stack.Push("xx")
stack.Push("yy")
it := stack.Iterator()
for it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty stack")
}
}
// NextTo (found)
{
stack := New()
stack.Push("aa")
stack.Push("bb")
stack.Push("cc")
it := stack.Iterator()
it.Begin()
if !it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty stack")
}
if index, value := it.Index(), it.Value(); index != 1 || value.(string) != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Next() {
t.Errorf("Should go to first element")
}
if index, value := it.Index(), it.Value(); index != 2 || value.(string) != "aa" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "aa")
}
if it.Next() {
t.Errorf("Should not go past last element")
}
}
}
func TestStackIteratorPrevTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index int, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
}
// PrevTo (empty)
{
stack := New()
it := stack.Iterator()
it.End()
for it.PrevTo(seek) {
t.Errorf("Shouldn't iterate on empty stack")
}
}
// PrevTo (not found)
{
stack := New()
stack.Push("xx")
stack.Push("yy")
it := stack.Iterator()
it.End()
for it.PrevTo(seek) {
t.Errorf("Shouldn't iterate on empty stack")
}
}
// PrevTo (found)
{
stack := New()
stack.Push("aa")
stack.Push("bb")
stack.Push("cc")
it := stack.Iterator()
it.End()
if !it.PrevTo(seek) {
t.Errorf("Shouldn't iterate on empty stack")
}
if index, value := it.Index(), it.Value(); index != 1 || value.(string) != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Prev() {
t.Errorf("Should go to first element")
}
if index, value := it.Index(), it.Value(); index != 0 || value.(string) != "cc" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "cc")
}
if it.Prev() {
t.Errorf("Should not go before first element")
}
}
}
func TestStackSerialization(t *testing.T) {
stack := New()
stack.Push("a")
+28
View File
@@ -82,3 +82,31 @@ func (iterator *Iterator) Last() bool {
iterator.End()
return iterator.Prev()
}
// NextTo moves the iterator to the next element from current position that satisfies the condition given by the
// passed function, and returns true if there was a next element in the container.
// If NextTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) NextTo(f func(index int, value interface{}) bool) bool {
for iterator.Next() {
index, value := iterator.Index(), iterator.Value()
if f(index, value) {
return true
}
}
return false
}
// PrevTo moves the iterator to the previous element from current position that satisfies the condition given by the
// passed function, and returns true if there was a next element in the container.
// If PrevTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) PrevTo(f func(index int, value interface{}) bool) bool {
for iterator.Prev() {
index, value := iterator.Index(), iterator.Value()
if f(index, value) {
return true
}
}
return false
}