1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-04 12:52:28 +08:00

feat: update iterator package

This commit is contained in:
dudaodong
2022-11-29 13:58:48 +08:00
parent a99ada5ee1
commit eb66d038ac
3 changed files with 145 additions and 58 deletions

View File

@@ -1,68 +1,144 @@
// Copyright 2021 dudaodong@gmail.com. All rights resulterved.
// Copyright 2022 dudaodong@gmail.com. All rights resulterved.
// Use of this source code is governed by MIT license
// Package iterator implements some feature of C++ STL iterators
// Package iterator provides a way to iterate over values stored in containers.
// note:
// 1. Full feature iterator is complicated, this pacakge is just a experiment to explore how iterators could work in Go.
// 2. The functionality of this package is very simple and limited, may not meet the actual dev needs.
// 3. It is currently under development, unstable, and will not be completed for some time in the future.
// So, based on above factors, you may not use it in production. but, anyone is welcome to improve it.
// Hope that Go can support iterator in future. see https://github.com/golang/go/discussions/54245 and https://github.com/golang/go/discussions/56413
package iterator
import "github.com/duke-git/lancet/v2/lancetconstraints"
// Iterator is used to iterate over a slice of data.
// Iterator supports iterating over a sequence of values of type `E`.
type Iterator[T any] interface {
// Next checks if there is a next value in the iteration or not
HasNext() bool
Next() (T, bool)
// Next returns the next value in the iteration if there is one,
// and reports whether the returned value is valid.
// Once Next returns ok==false, the iteration is over,
// and all subsequent calls will return ok==false.
Next() (item T, ok bool)
}
// StopIterator is an interface for stopping Iterator.
type StopIterator[T any] interface {
Iterator[T]
// Stop indicates that the iterator will no longer be used.
// After a call to Stop, future calls to Next may panic.
// Stop may be called multiple times;
// all calls after the first will have no effect.
Stop()
}
// DeleteIter is an Iter that implements a Delete method.
type DeleteIterator[T any] interface {
Iterator[T]
// Delete deletes the current iterator element;
// that is, the one returned by the last call to Next.
// Delete should panic if called before Next or after
// Next returns false.
Delete()
}
// SetIterator is an Iter that implements a Set method.
type SetIterator[T any] interface {
Iterator[T]
// Set replaces the current iterator element with v.
// Set should panic if called before Next or after
// Next returns false.
Set(v T)
}
// PrevIterator is an iterator with a Prev method.
type PrevIterator[T any] interface {
Iterator[T]
// Prev moves the iterator to the previous position.
// After calling Prev, Next will return the value at
// that position in the container. For example, after
// it.Next() returning (v, true)
// it.Prev()
// another call to it.Next will again return (v, true).
// Calling Prev before calling Next may panic.
// Calling Prev after Next returns false will move
// to the last element, or, if there are no elements,
// to the iterator's initial state.
Prev()
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Functions that create an Iterator from some other type. //
////////////////////////////////////////////////////////////////////////////////////////////////////
// FromSlice returns an iterator over a slice of data.
func FromSlice[T any](data []T) Iterator[T] {
// return &sliceIterator[T]{slice: data, index: 0, step: 1}
return &sliceIterator[T]{slice: data}
func FromSlice[T any](slice []T) Iterator[T] {
return &sliceIterator[T]{slice: slice, index: -1}
}
func ToSlice[T any](iter Iterator[T]) []T {
result := []T{}
for item, ok := iter.Next(); ok; item, ok = iter.Next() {
result = append(result, item)
}
return result
}
type sliceIterator[T any] struct {
slice []T
// index int
// step int
index int
}
func (iter *sliceIterator[T]) HasNext() bool {
if len(iter.slice) == 0 {
return false
}
return true
return iter.index < len(iter.slice)-1
}
func (iter *sliceIterator[T]) Next() (T, bool) {
if len(iter.slice) == 0 {
var zero T
return zero, false
iter.index++
ok := iter.index >= 0 && iter.index < len(iter.slice)
var item T
if ok {
item = iter.slice[iter.index]
}
item := iter.slice[0]
iter.slice = iter.slice[1:]
return item, true
return item, ok
// if len(iter.slice) == 0 {
// var zero T
// return zero, false
// }
// iter.index++
// item := iter.slice[0]
// iter.slice = iter.slice[1:]
// return item, true
}
// Count
func (iter *sliceIterator[T]) Count() int {
count := len(iter.slice)
iter.slice = []T{}
return count
// Prev implements PrevIterator.
func (iter *sliceIterator[T]) Prev() {
if iter.index == -1 {
panic("Next function should be called Prev")
}
if iter.HasNext() {
iter.index--
} else {
iter.index = len(iter.slice) - 1
}
}
// func (iter *sliceIterator[T]) Begin(data []T) Iterator[T] {
// iter.data = data
// iter.index = 0
// iter.step = 1
// return iter
// }
// func (iter *sliceIterator[T]) End(data []T) Iterator[T] {
// iter.data = data
// iter.index = len(data)
// iter.step = 1
// return iter
// }
// Set implements SetIterator.
func (iter *sliceIterator[T]) Set(value T) {
if iter.index == -1 {
panic("Next function should be called Set")
}
if iter.index >= len(iter.slice) || len(iter.slice) == 0 {
panic("No element in current iterator")
}
iter.slice[iter.index] = value
}
// FromRange creates a iterator which returns the numeric range between start inclusive and end
// exclusive by the step size. start should be less than end, step shoud be positive.
@@ -96,9 +172,3 @@ func (iter *rangeIterator[T]) Next() (T, bool) {
iter.start += iter.step
return num, true
}
func (iter *rangeIterator[T]) Count() int {
count := (iter.end - iter.start) / iter.step
iter.start = iter.end
return int(count)
}

View File

@@ -1,4 +1,4 @@
// Copyright 2021 dudaodong@gmail.com. All rights resulterved.
// Copyright 2022 dudaodong@gmail.com. All rights resulterved.
// Use of this source code is governed by MIT license
// Package iterator implements some feature of C++ STL iterators
@@ -13,27 +13,38 @@ import (
func TestSliceIterator(t *testing.T) {
assert := internal.NewAssert(t, "TestSliceIterator")
t.Run("slice iterator has next", func(t *testing.T) {
iter := FromSlice([]int{1, 2, 3, 4})
// HashNext
t.Run("slice iterator HasNext: ", func(t *testing.T) {
iter1 := FromSlice([]int{1, 2, 3, 4})
for {
item, _ := iter.Next()
if item < 4 {
assert.Equal(true, iter.HasNext())
} else {
assert.Equal(false, iter.HasNext())
item, _ := iter1.Next()
if item == 4 {
assert.Equal(false, iter1.HasNext())
break
} else {
assert.Equal(true, iter1.HasNext())
}
}
iter2 := FromSlice([]int{})
assert.Equal(false, iter2.HasNext())
})
t.Run("slice iterator next", func(t *testing.T) {
iter := FromSlice([]int{1, 2, 3, 4})
//Next
t.Run("slice iterator Next: ", func(t *testing.T) {
iter1 := FromSlice([]int{1, 2, 3, 4})
for i := 0; i < 4; i++ {
item, ok := iter.Next()
item, ok := iter1.Next()
if !ok {
break
}
assert.Equal(i+1, item)
}
iter2 := FromSlice([]int{})
_, ok := iter2.Next()
assert.Equal(false, ok)
})
}

View File

@@ -1,7 +1,13 @@
// Copyright 2021 dudaodong@gmail.com. All rights resulterved.
// Copyright 2022 dudaodong@gmail.com. All rights resulterved.
// Use of this source code is governed by MIT license
// Package iterator implements some feature of C++ STL iterators
// Package iterator provides a way to iterate over values stored in containers.
// note:
// 1. Full feature iterator is complicated, this pacakge is just a experiment to explore how iterators could work in Go.
// 2. The functionality of this package is very simple and limited, may not meet the actual dev needs.
// 3. It is currently under development, unstable, and will not be completed for some time in the future.
// So, based on above factors, you may not use it in production. but, anyone is welcome to improve it.
// Hope that Go can support iterator in future. see https://github.com/golang/go/discussions/54245 and https://github.com/golang/go/discussions/56413
package iterator
// Map creates a new iterator which applies a function to all items of input iterator.