Skip to content

Commit

Permalink
Merge pull request #190 from emirpasic/development
Browse files Browse the repository at this point in the history
Development
  • Loading branch information
emirpasic authored Apr 11, 2022
2 parents 057bca0 + 17e5fd5 commit 55346e9
Show file tree
Hide file tree
Showing 32 changed files with 1,890 additions and 14 deletions.
78 changes: 73 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[![GoDoc](https://godoc.org/github.com/emirpasic/gods?status.svg)](https://godoc.org/github.com/emirpasic/gods) [![Build Status](https://circleci.com/gh/emirpasic/gods/tree/master.svg?style=shield)](https://circleci.com/gh/emirpasic/gods?branch=master) [![Go Report Card](https://goreportcard.com/badge/github.com/emirpasic/gods)](https://goreportcard.com/report/github.com/emirpasic/gods) [![PyPI](https://img.shields.io/pypi/l/Django.svg?maxAge=2592000)](https://github.com/emirpasic/gods/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/emirpasic/gods?status.svg)](https://godoc.org/github.com/emirpasic/gods) [![Build Status](https://circleci.com/gh/emirpasic/gods/tree/master.svg?style=shield)](https://circleci.com/gh/emirpasic/gods?branch=master) [![Go Report Card](https://goreportcard.com/badge/github.com/emirpasic/gods)](https://goreportcard.com/report/github.com/emirpasic/gods) [![PyPI](https://img.shields.io/badge/License-BSD_2--Clause-green.svg)](https://github.com/emirpasic/gods/blob/master/LICENSE)

# GoDS (Go Data Structures)

Expand Down Expand Up @@ -983,6 +983,22 @@ for it.Begin(); it.Next(); {
}
```

Seeking to a specific element:

```go
// Seek function, i.e. find element starting with "b"
seek := func(index int, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
}

// Seek to the condition and continue traversal from that point (forward).
// assumes it.Begin() was called.
for found := it.NextTo(seek); found; found = it.Next() {
index, value := it.Index(), it.Value()
...
}
```

#### IteratorWithKey

An [iterator](#iterator) whose elements are referenced by a key.
Expand Down Expand Up @@ -1010,6 +1026,22 @@ for it.Begin(); it.Next(); {
}
```

Seeking to a specific element from the current iterator position:

```go
// Seek function, i.e. find element starting with "b"
seek := func(key interface{}, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
}

// Seek to the condition and continue traversal from that point (forward).
// assumes it.Begin() was called.
for found := it.NextTo(seek); found; found = it.Next() {
key, value := it.Key(), it.Value()
...
}
```

#### ReverseIteratorWithIndex

An [iterator](#iterator) whose elements are referenced by an index. Provides all functions as [IteratorWithIndex](#iteratorwithindex), but can also be used for reverse iteration.
Expand All @@ -1031,6 +1063,22 @@ if it.Last() {
}
```

Seeking to a specific element:

```go
// Seek function, i.e. find element starting with "b"
seek := func(index int, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
}

// Seek to the condition and continue traversal from that point (in reverse).
// assumes it.End() was called.
for found := it.PrevTo(seek); found; found = it.Prev() {
index, value := it.Index(), it.Value()
...
}
```

#### ReverseIteratorWithKey

An [iterator](#iterator) whose elements are referenced by a key. Provides all functions as [IteratorWithKey](#iteratorwithkey), but can also be used for reverse iteration.
Expand All @@ -1052,6 +1100,20 @@ if it.Last() {
}
```

```go
// Seek function, i.e. find element starting with "b"
seek := func(key interface{}, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
}

// Seek to the condition and continue traversal from that point (in reverse).
// assumes it.End() was called.
for found := it.PrevTo(seek); found; found = it.Prev() {
key, value := it.Key(), it.Value()
...
}
```

### Enumerable

Enumerable functions for ordered containers that implement [EnumerableWithIndex](#enumerablewithindex) or [EnumerableWithKey](#enumerablewithkey) interfaces.
Expand Down Expand Up @@ -1489,13 +1551,19 @@ Coding style:
```shell
# Install tooling and set path:
go get github.com/golang/lint/golint
go get github.com/fzipp/gocyclo
go get github.com/kisielk/errcheck
go install gotest.tools/gotestsum@latest
go install golang.org/x/lint/golint@latest
go install github.com/kisielk/errcheck@latest
export PATH=$PATH:$GOPATH/bin

# Fix errors and warnings:
go fmt ./... && gofmt -s -w . && go vet ./... && go get ./... && go test ./... && golint ./... && gocyclo -avg -over 15 . && errcheck ./...
go fmt ./... &&
go test -v ./... &&
golint -set_exit_status ./... &&
! go fmt ./... 2>&1 | read &&
go vet -v ./... &&
gocyclo -avg -over 15 ../gods &&
errcheck ./...
```
### License
Expand Down
24 changes: 24 additions & 0 deletions containers/iterator.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ type IteratorWithIndex interface {
// If First() returns true, then first element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
First() bool

// 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.
NextTo(func(index int, value interface{}) bool) bool
}

// IteratorWithKey is a stateful iterator for ordered containers whose elements are key value pairs.
Expand All @@ -54,6 +60,12 @@ type IteratorWithKey interface {
// If First() returns true, then first element's key and value can be retrieved by Key() and Value().
// Modifies the state of the iterator.
First() bool

// 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 key and value can be retrieved by Key() and Value().
// Modifies the state of the iterator.
NextTo(func(key interface{}, value interface{}) bool) bool
}

// ReverseIteratorWithIndex is stateful iterator for ordered containers whose values can be fetched by an index.
Expand All @@ -80,6 +92,12 @@ type ReverseIteratorWithIndex interface {
// Modifies the state of the iterator.
Last() bool

// 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.
PrevTo(func(index int, value interface{}) bool) bool

IteratorWithIndex
}

Expand All @@ -105,5 +123,11 @@ type ReverseIteratorWithKey interface {
// Modifies the state of the iterator.
Last() bool

// 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 key and value can be retrieved by Key() and Value().
// Modifies the state of the iterator.
PrevTo(func(key interface{}, value interface{}) bool) bool

IteratorWithKey
}
29 changes: 29 additions & 0 deletions examples/iteratorwithindex/iteratorwithindex.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package main
import (
"fmt"
"github.com/emirpasic/gods/sets/treeset"
"strings"
)

// IteratorWithIndexExample to demonstrate basic usage of IteratorWithIndex
Expand Down Expand Up @@ -48,4 +49,32 @@ func main() {
fmt.Print("\nLast index: ", it.Index()) // Last index: 3
fmt.Print("\nLast value: ", it.Value()) // Last value: c
}

// Seek element starting with "b"
seek := func(index int, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
}

it.Begin()
for found := it.NextTo(seek); found; found = it.Next() {
fmt.Print("\nNextTo index: ", it.Index())
fmt.Print("\nNextTo value: ", it.Value())
} /*
NextTo index: 1
NextTo value: "b"
NextTo index: 2
NextTo value: "c"
*/

it.End()
for found := it.PrevTo(seek); found; found = it.Prev() {
fmt.Print("\nNextTo index: ", it.Index())
fmt.Print("\nNextTo value: ", it.Value())
} /*
NextTo index: 1
NextTo value: "b"
NextTo index: 0
NextTo value: "a"
*/

}
36 changes: 32 additions & 4 deletions examples/iteratorwithkey/iteratorwithkey.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ package main
import (
"fmt"
"github.com/emirpasic/gods/maps/treemap"
"strings"
)

// IteratorWithKeyExample to demonstrate basic usage of IteratorWithKey
func main() {
m := treemap.NewWithIntComparator()
m.Put(1, "a")
m.Put(2, "b")
m.Put(3, "a")
m.Put(0, "a")
m.Put(1, "b")
m.Put(2, "c")
it := m.Iterator()

fmt.Print("\nForward iteration\n")
Expand Down Expand Up @@ -47,7 +48,34 @@ func main() {
}

if it.Last() {
fmt.Print("\nLast key: ", it.Key()) // Last key: 3
fmt.Print("\nLast key: ", it.Key()) // Last key: 2
fmt.Print("\nLast value: ", it.Value()) // Last value: c
}

// Seek key-value pair whose value starts with "b"
seek := func(key interface{}, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
}

it.Begin()
for found := it.NextTo(seek); found; found = it.Next() {
fmt.Print("\nNextTo key: ", it.Key())
fmt.Print("\nNextTo value: ", it.Value())
} /*
NextTo key: 1
NextTo value: "b"
NextTo key: 2
NextTo value: "c"
*/

it.End()
for found := it.PrevTo(seek); found; found = it.Prev() {
fmt.Print("\nNextTo key: ", it.Key())
fmt.Print("\nNextTo value: ", it.Value())
} /*
NextTo key: 1
NextTo value: "b"
NextTo key: 0
NextTo value: "a"
*/
}
101 changes: 101 additions & 0 deletions lists/arraylist/arraylist_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package arraylist
import (
"fmt"
"github.com/emirpasic/gods/utils"
"strings"
"testing"
)

Expand Down Expand Up @@ -500,6 +501,106 @@ func TestListIteratorLast(t *testing.T) {
}
}

func TestListIteratorNextTo(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)
{
list := New()
it := list.Iterator()
for it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty list")
}
}

// NextTo (not found)
{
list := New()
list.Add("xx", "yy")
it := list.Iterator()
for it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty list")
}
}

// NextTo (found)
{
list := New()
list.Add("aa", "bb", "cc")
it := list.Iterator()
it.Begin()
if !it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty list")
}
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) != "cc" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "cc")
}
if it.Next() {
t.Errorf("Should not go past last element")
}
}
}

func TestListIteratorPrevTo(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)
{
list := New()
it := list.Iterator()
it.End()
for it.PrevTo(seek) {
t.Errorf("Shouldn't iterate on empty list")
}
}

// PrevTo (not found)
{
list := New()
list.Add("xx", "yy")
it := list.Iterator()
it.End()
for it.PrevTo(seek) {
t.Errorf("Shouldn't iterate on empty list")
}
}

// PrevTo (found)
{
list := New()
list.Add("aa", "bb", "cc")
it := list.Iterator()
it.End()
if !it.PrevTo(seek) {
t.Errorf("Shouldn't iterate on empty list")
}
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) != "aa" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "aa")
}
if it.Prev() {
t.Errorf("Should not go before first element")
}
}
}

func TestListSerialization(t *testing.T) {
list := New()
list.Add("a", "b", "c")
Expand Down
Loading

0 comments on commit 55346e9

Please sign in to comment.