- add enumerable and iterator to singly linked list

pull/12/head
Emir Pasic 9 years ago
parent 60c2f3af71
commit 76f36e4980

@ -32,6 +32,7 @@ package singlylinkedlist
import (
"fmt"
"github.com/emirpasic/gods/containers"
"github.com/emirpasic/gods/lists"
"github.com/emirpasic/gods/utils"
"strings"
@ -39,6 +40,8 @@ import (
func assertInterfaceImplementation() {
var _ lists.List = (*List)(nil)
var _ containers.Enumerable = (*List)(nil)
var _ containers.Iterator = (*Iterator)(nil)
}
type List struct {
@ -267,6 +270,95 @@ func (list *List) Insert(index int, values ...interface{}) {
}
}
type Iterator struct {
list *List
index int
element *element
}
func (list *List) Iterator() Iterator {
return Iterator{list: list, index: -1, element: nil}
}
func (iterator *Iterator) Next() bool {
iterator.index += 1
if !iterator.list.withinRange(iterator.index) {
iterator.element = nil
return false
}
if iterator.element == nil {
iterator.element = iterator.list.first
} else {
iterator.element = iterator.element.next
}
return true
}
func (iterator *Iterator) Value() interface{} {
return iterator.element.value
}
func (iterator *Iterator) Index() interface{} {
return iterator.index
}
func (list *List) Each(f func(index interface{}, value interface{})) {
iterator := list.Iterator()
for iterator.Next() {
f(iterator.Index(), iterator.Value())
}
}
func (list *List) Map(f func(index interface{}, value interface{}) interface{}) containers.Container {
newList := &List{}
iterator := list.Iterator()
for iterator.Next() {
newList.Add(f(iterator.Index(), iterator.Value()))
}
return newList
}
func (list *List) Select(f func(index interface{}, value interface{}) bool) containers.Container {
newList := &List{}
iterator := list.Iterator()
for iterator.Next() {
if f(iterator.Index(), iterator.Value()) {
newList.Add(iterator.Value())
}
}
return newList
}
func (list *List) Any(f func(index interface{}, value interface{}) bool) bool {
iterator := list.Iterator()
for iterator.Next() {
if f(iterator.Index(), iterator.Value()) {
return true
}
}
return false
}
func (list *List) All(f func(index interface{}, value interface{}) bool) bool {
iterator := list.Iterator()
for iterator.Next() {
if !f(iterator.Index(), iterator.Value()) {
return false
}
}
return true
}
func (list *List) Find(f func(index interface{}, value interface{}) bool) (index interface{}, value interface{}) {
iterator := list.Iterator()
for iterator.Next() {
if f(iterator.Index(), iterator.Value()) {
return iterator.Index(), iterator.Value()
}
}
return nil, nil
}
func (list *List) String() string {
str := "SinglyLinkedList\n"
values := []string{}

@ -135,7 +135,132 @@ func TestSinglyLinkedList(t *testing.T) {
if actualValue, expectedValue := fmt.Sprintf("%s%s%s%s%s%s%s%s%s%s%s", list.Values()...), "abcdefghijk"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
}
func TestSinglyLinkedListEnumerableAndIterator(t *testing.T) {
list := New()
list.Add("a", "b", "c")
// Each
list.Each(func(index interface{}, value interface{}) {
switch index {
case 0:
if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
case 1:
if actualValue, expectedValue := value, "b"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
case 2:
if actualValue, expectedValue := value, "c"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
default:
t.Errorf("Too many")
}
})
// Map
mappedList := list.Map(func(index interface{}, value interface{}) interface{} {
return "mapped: " + value.(string)
}).(*List)
if actualValue, _ := mappedList.Get(0); actualValue != "mapped: a" {
t.Errorf("Got %v expected %v", actualValue, "mapped: a")
}
if actualValue, _ := mappedList.Get(1); actualValue != "mapped: b" {
t.Errorf("Got %v expected %v", actualValue, "mapped: b")
}
if actualValue, _ := mappedList.Get(2); actualValue != "mapped: c" {
t.Errorf("Got %v expected %v", actualValue, "mapped: c")
}
if mappedList.Size() != 3 {
t.Errorf("Got %v expected %v", mappedList.Size(), 3)
}
// Select
selectedList := list.Select(func(index interface{}, value interface{}) bool {
return value.(string) >= "a" && value.(string) <= "b"
}).(*List)
if actualValue, _ := selectedList.Get(0); actualValue != "a" {
t.Errorf("Got %v expected %v", actualValue, "value: a")
}
if actualValue, _ := selectedList.Get(1); actualValue != "b" {
t.Errorf("Got %v expected %v", actualValue, "value: b")
}
if selectedList.Size() != 2 {
t.Errorf("Got %v expected %v", selectedList.Size(), 3)
}
// Any
any := list.Any(func(index interface{}, value interface{}) bool {
return value.(string) == "c"
})
if any != true {
t.Errorf("Got %v expected %v", any, true)
}
any = list.Any(func(index interface{}, value interface{}) bool {
return value.(string) == "x"
})
if any != false {
t.Errorf("Got %v expected %v", any, false)
}
// All
all := list.All(func(index interface{}, value interface{}) bool {
return value.(string) >= "a" && value.(string) <= "c"
})
if all != true {
t.Errorf("Got %v expected %v", all, true)
}
all = list.All(func(index interface{}, value interface{}) bool {
return value.(string) >= "a" && value.(string) <= "b"
})
if all != false {
t.Errorf("Got %v expected %v", all, false)
}
// Find
foundIndex, foundValue := list.Find(func(index interface{}, value interface{}) bool {
return value.(string) == "c"
})
if foundValue != "c" || foundIndex != 2 {
t.Errorf("Got %v at %v expected %v at %v", foundValue, foundIndex, "c", 2)
}
foundIndex, foundValue = list.Find(func(index interface{}, value interface{}) bool {
return value.(string) == "x"
})
if foundValue != nil || foundIndex != nil {
t.Errorf("Got %v at %v expected %v at %v", foundValue, foundIndex, nil, nil)
}
// Iterator
it := list.Iterator()
for it.Next() {
index := it.Index()
value := it.Value()
switch index {
case 0:
if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
case 1:
if actualValue, expectedValue := value, "b"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
case 2:
if actualValue, expectedValue := value, "c"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
default:
t.Errorf("Too many")
}
}
list.Clear()
it = list.Iterator()
for it.Next() {
t.Errorf("Shouldn't iterate on empty list")
}
}
func BenchmarkSinglyLinkedList(b *testing.B) {

Loading…
Cancel
Save