From 60c2f3af712d112c95ed4dc290003fd739b8434c Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Wed, 22 Jun 2016 05:26:48 +0200 Subject: [PATCH] - add enumerable and iterator to doubly linked list --- lists/arraylist/arraylist.go | 20 +-- lists/arraylist/arraylist_test.go | 1 - lists/doublylinkedlist/doublylinkedlist.go | 92 +++++++++++++ .../doublylinkedlist/doublylinkedlist_test.go | 125 ++++++++++++++++++ 4 files changed, 227 insertions(+), 11 deletions(-) diff --git a/lists/arraylist/arraylist.go b/lists/arraylist/arraylist.go index c0e313f..059ef3e 100644 --- a/lists/arraylist/arraylist.go +++ b/lists/arraylist/arraylist.go @@ -178,21 +178,26 @@ func (list *List) Insert(index int, values ...interface{}) { } } +type Iterator struct { + list *List + index int +} + func (list *List) Iterator() Iterator { - return Iterator{list: list, current: -1} + return Iterator{list: list, index: -1} } func (iterator *Iterator) Next() bool { - iterator.current += 1 - return iterator.list.withinRange(iterator.current) + iterator.index += 1 + return iterator.list.withinRange(iterator.index) } func (iterator *Iterator) Value() interface{} { - return iterator.list.elements[iterator.current] + return iterator.list.elements[iterator.index] } func (iterator *Iterator) Index() interface{} { - return iterator.current + return iterator.index } func (list *List) Each(f func(index interface{}, value interface{})) { @@ -252,11 +257,6 @@ func (list *List) Find(f func(index interface{}, value interface{}) bool) (index return nil, nil } -type Iterator struct { - list *List - current int -} - func (list *List) String() string { str := "ArrayList\n" values := []string{} diff --git a/lists/arraylist/arraylist_test.go b/lists/arraylist/arraylist_test.go index ac25687..2ec424f 100644 --- a/lists/arraylist/arraylist_test.go +++ b/lists/arraylist/arraylist_test.go @@ -133,7 +133,6 @@ func TestArrayList(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 TestArrayListEnumerableAndIterator(t *testing.T) { diff --git a/lists/doublylinkedlist/doublylinkedlist.go b/lists/doublylinkedlist/doublylinkedlist.go index 281bda1..69d6368 100644 --- a/lists/doublylinkedlist/doublylinkedlist.go +++ b/lists/doublylinkedlist/doublylinkedlist.go @@ -32,6 +32,7 @@ package doublylinkedlist 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 { @@ -297,6 +300,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 := "DoublyLinkedList\n" values := []string{} diff --git a/lists/doublylinkedlist/doublylinkedlist_test.go b/lists/doublylinkedlist/doublylinkedlist_test.go index 528b00f..a5c6dcd 100644 --- a/lists/doublylinkedlist/doublylinkedlist_test.go +++ b/lists/doublylinkedlist/doublylinkedlist_test.go @@ -135,7 +135,132 @@ func TestDoublyLinkedList(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 TestDoublyLinkedListEnumerableAndIterator(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 BenchmarkDoublyLinkedList(b *testing.B) {