From b41257272c91ce84368d29e347621c8804030684 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Sun, 3 Jul 2016 03:47:35 +0200 Subject: [PATCH] - TreeBidiMap enumerable implemented (with tests) --- maps/treebidimap/enumerable.go | 80 ++++++++++++++ maps/treebidimap/treebidimap.go | 12 ++- maps/treebidimap/treebidimap_test.go | 152 +++++++++++++++++++++++++++ maps/treemap/treemap_test.go | 8 +- 4 files changed, 244 insertions(+), 8 deletions(-) create mode 100644 maps/treebidimap/enumerable.go diff --git a/maps/treebidimap/enumerable.go b/maps/treebidimap/enumerable.go new file mode 100644 index 0000000..d5d829a --- /dev/null +++ b/maps/treebidimap/enumerable.go @@ -0,0 +1,80 @@ +// Copyright (c) 2015, Emir Pasic. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package treebidimap + +import "github.com/emirpasic/gods/containers" + +func assertEnumerableImplementation() { + var _ containers.EnumerableWithKey = (*Map)(nil) +} + +// Each calls the given function once for each element, passing that element's key and value. +func (m *Map) Each(f func(key interface{}, value interface{})) { + iterator := m.Iterator() + for iterator.Next() { + f(iterator.Key(), iterator.Value()) + } +} + +// Map invokes the given function once for each element and returns a container +// containing the values returned by the given function as key/value pairs. +func (m *Map) Map(f func(key1 interface{}, value1 interface{}) (interface{}, interface{})) *Map { + newMap := NewWith(m.keyComparator, m.valueComparator) + iterator := m.Iterator() + for iterator.Next() { + key2, value2 := f(iterator.Key(), iterator.Value()) + newMap.Put(key2, value2) + } + return newMap +} + +// Select returns a new container containing all elements for which the given function returns a true value. +func (m *Map) Select(f func(key interface{}, value interface{}) bool) *Map { + newMap := NewWith(m.keyComparator, m.valueComparator) + iterator := m.Iterator() + for iterator.Next() { + if f(iterator.Key(), iterator.Value()) { + newMap.Put(iterator.Key(), iterator.Value()) + } + } + return newMap +} + +// Any passes each element of the container to the given function and +// returns true if the function ever returns true for any element. +func (m *Map) Any(f func(key interface{}, value interface{}) bool) bool { + iterator := m.Iterator() + for iterator.Next() { + if f(iterator.Key(), iterator.Value()) { + return true + } + } + return false +} + +// All passes each element of the container to the given function and +// returns true if the function returns true for all elements. +func (m *Map) All(f func(key interface{}, value interface{}) bool) bool { + iterator := m.Iterator() + for iterator.Next() { + if !f(iterator.Key(), iterator.Value()) { + return false + } + } + return true +} + +// Find passes each element of the container to the given function and returns +// the first (key,value) for which the function is true or nil,nil otherwise if no element +// matches the criteria. +func (m *Map) Find(f func(key interface{}, value interface{}) bool) (interface{}, interface{}) { + iterator := m.Iterator() + for iterator.Next() { + if f(iterator.Key(), iterator.Value()) { + return iterator.Key(), iterator.Value() + } + } + return nil, nil +} diff --git a/maps/treebidimap/treebidimap.go b/maps/treebidimap/treebidimap.go index 2855542..342e2cf 100644 --- a/maps/treebidimap/treebidimap.go +++ b/maps/treebidimap/treebidimap.go @@ -30,8 +30,10 @@ func assertMapImplementation() { // Map holds the elements in two red-black trees. type Map struct { - forwardMap redblacktree.Tree - inverseMap redblacktree.Tree + forwardMap redblacktree.Tree + inverseMap redblacktree.Tree + keyComparator utils.Comparator + valueComparator utils.Comparator } type data struct { @@ -42,8 +44,10 @@ type data struct { // NewWith instantiates a bidirectional map. func NewWith(keyComparator utils.Comparator, valueComparator utils.Comparator) *Map { return &Map{ - forwardMap: *redblacktree.NewWith(keyComparator), - inverseMap: *redblacktree.NewWith(valueComparator), + forwardMap: *redblacktree.NewWith(keyComparator), + inverseMap: *redblacktree.NewWith(valueComparator), + keyComparator: keyComparator, + valueComparator: valueComparator, } } diff --git a/maps/treebidimap/treebidimap_test.go b/maps/treebidimap/treebidimap_test.go index 40b3497..5c41961 100644 --- a/maps/treebidimap/treebidimap_test.go +++ b/maps/treebidimap/treebidimap_test.go @@ -170,6 +170,158 @@ func sameElements(a []interface{}, b []interface{}) bool { return true } +func TestMapEach(t *testing.T) { + m := NewWith(utils.StringComparator, utils.IntComparator) + m.Put("c", 3) + m.Put("a", 1) + m.Put("b", 2) + count := 0 + m.Each(func(key interface{}, value interface{}) { + count++ + if actualValue, expectedValue := count, value; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + switch value { + case 1: + if actualValue, expectedValue := key, "a"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + case 2: + if actualValue, expectedValue := key, "b"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + case 3: + if actualValue, expectedValue := key, "c"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + default: + t.Errorf("Too many") + } + }) +} + +func TestMapMap(t *testing.T) { + m := NewWith(utils.StringComparator, utils.IntComparator) + m.Put("c", 3) + m.Put("a", 1) + m.Put("b", 2) + mappedMap := m.Map(func(key1 interface{}, value1 interface{}) (key2 interface{}, value2 interface{}) { + return key1, value1.(int) * value1.(int) + }) + if actualValue, _ := mappedMap.Get("a"); actualValue != 1 { + t.Errorf("Got %v expected %v", actualValue, "mapped: a") + } + if actualValue, _ := mappedMap.Get("b"); actualValue != 4 { + t.Errorf("Got %v expected %v", actualValue, "mapped: b") + } + if actualValue, _ := mappedMap.Get("c"); actualValue != 9 { + t.Errorf("Got %v expected %v", actualValue, "mapped: c") + } + if mappedMap.Size() != 3 { + t.Errorf("Got %v expected %v", mappedMap.Size(), 3) + } +} + +func TestMapSelect(t *testing.T) { + m := NewWith(utils.StringComparator, utils.IntComparator) + m.Put("c", 3) + m.Put("a", 1) + m.Put("b", 2) + selectedMap := m.Select(func(key interface{}, value interface{}) bool { + return key.(string) >= "a" && key.(string) <= "b" + }) + if actualValue, _ := selectedMap.Get("a"); actualValue != 1 { + t.Errorf("Got %v expected %v", actualValue, "value: a") + } + if actualValue, _ := selectedMap.Get("b"); actualValue != 2 { + t.Errorf("Got %v expected %v", actualValue, "value: b") + } + if selectedMap.Size() != 2 { + t.Errorf("Got %v expected %v", selectedMap.Size(), 2) + } +} + +func TestMapAny(t *testing.T) { + m := NewWith(utils.StringComparator, utils.IntComparator) + m.Put("c", 3) + m.Put("a", 1) + m.Put("b", 2) + any := m.Any(func(key interface{}, value interface{}) bool { + return value.(int) == 3 + }) + if any != true { + t.Errorf("Got %v expected %v", any, true) + } + any = m.Any(func(key interface{}, value interface{}) bool { + return value.(int) == 4 + }) + if any != false { + t.Errorf("Got %v expected %v", any, false) + } +} + +func TestMapAll(t *testing.T) { + m := NewWith(utils.StringComparator, utils.IntComparator) + m.Put("c", 3) + m.Put("a", 1) + m.Put("b", 2) + all := m.All(func(key interface{}, value interface{}) bool { + return key.(string) >= "a" && key.(string) <= "c" + }) + if all != true { + t.Errorf("Got %v expected %v", all, true) + } + all = m.All(func(key interface{}, value interface{}) bool { + return key.(string) >= "a" && key.(string) <= "b" + }) + if all != false { + t.Errorf("Got %v expected %v", all, false) + } +} + +func TestMapFind(t *testing.T) { + m := NewWith(utils.StringComparator, utils.IntComparator) + m.Put("c", 3) + m.Put("a", 1) + m.Put("b", 2) + foundKey, foundValue := m.Find(func(key interface{}, value interface{}) bool { + return key.(string) == "c" + }) + if foundKey != "c" || foundValue != 3 { + t.Errorf("Got %v -> %v expected %v -> %v", foundKey, foundValue, "c", 3) + } + foundKey, foundValue = m.Find(func(key interface{}, value interface{}) bool { + return key.(string) == "x" + }) + if foundKey != nil || foundValue != nil { + t.Errorf("Got %v at %v expected %v at %v", foundValue, foundKey, nil, nil) + } +} + +func TestMapChaining(t *testing.T) { + m := NewWith(utils.StringComparator, utils.IntComparator) + m.Put("c", 3) + m.Put("a", 1) + m.Put("b", 2) + chainedMap := m.Select(func(key interface{}, value interface{}) bool { + return value.(int) > 1 + }).Map(func(key interface{}, value interface{}) (interface{}, interface{}) { + return key.(string) + key.(string), value.(int) * value.(int) + }) + if actualValue := chainedMap.Size(); actualValue != 2 { + t.Errorf("Got %v expected %v", actualValue, 2) + } + if actualValue, found := chainedMap.Get("aa"); actualValue != nil || found { + t.Errorf("Got %v expected %v", actualValue, nil) + } + if actualValue, found := chainedMap.Get("bb"); actualValue != 4 || !found { + t.Errorf("Got %v expected %v", actualValue, 4) + } + if actualValue, found := chainedMap.Get("cc"); actualValue != 9 || !found { + t.Errorf("Got %v expected %v", actualValue, 9) + } +} + func TestMapIteratorNextOnEmpty(t *testing.T) { m := NewWithStringComparators() it := m.Iterator() diff --git a/maps/treemap/treemap_test.go b/maps/treemap/treemap_test.go index 7240667..920b051 100644 --- a/maps/treemap/treemap_test.go +++ b/maps/treemap/treemap_test.go @@ -173,15 +173,15 @@ func TestMapMap(t *testing.T) { m.Put("a", 1) m.Put("b", 2) mappedMap := m.Map(func(key1 interface{}, value1 interface{}) (key2 interface{}, value2 interface{}) { - return key1, "mapped: " + key1.(string) + return key1, value1.(int) * value1.(int) }) - if actualValue, _ := mappedMap.Get("a"); actualValue != "mapped: a" { + if actualValue, _ := mappedMap.Get("a"); actualValue != 1 { t.Errorf("Got %v expected %v", actualValue, "mapped: a") } - if actualValue, _ := mappedMap.Get("b"); actualValue != "mapped: b" { + if actualValue, _ := mappedMap.Get("b"); actualValue != 4 { t.Errorf("Got %v expected %v", actualValue, "mapped: b") } - if actualValue, _ := mappedMap.Get("c"); actualValue != "mapped: c" { + if actualValue, _ := mappedMap.Get("c"); actualValue != 9 { t.Errorf("Got %v expected %v", actualValue, "mapped: c") } if mappedMap.Size() != 3 {