Remove duplicate implementation

This commit is contained in:
ionutboangiu
2023-05-25 02:54:39 -04:00
committed by Dan Christian Bogos
parent 5f890881f0
commit c83d097e9e
2 changed files with 0 additions and 251 deletions

View File

@@ -1,82 +0,0 @@
/*
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
Copyright (C) ITsysCOM GmbH
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package utils
// OrderedMap is a map that maintains the order of its key-value pairs.
type OrderedMap[K comparable, V any] struct {
keys []K // keys holds the keys in order of their insertion.
values map[K]V // values is a map of key-value pairs.
}
// NewOrderedMap creates a new ordered map and returns a pointer to it.
func NewOrderedMap[K comparable, V any]() *OrderedMap[K, V] {
return &OrderedMap[K, V]{
keys: make([]K, 0), // Initialize an empty slice for keys.
values: make(map[K]V), // Initialize an empty map for key-value pairs.
}
}
// Set adds a new key-value pair to the ordered map. If the key already exists, it updates the value.
func (om *OrderedMap[K, V]) Set(key K, value V) {
// If the key does not exist in the map, append it to the keys slice.
if _, exists := om.values[key]; !exists {
om.keys = append(om.keys, key)
}
// Add or update the value for the key in the map.
om.values[key] = value
}
// Get retrieves the value associated with the given key from the ordered map.
// It returns the value and a boolean indicating whether the key exists in the map.
func (om *OrderedMap[K, V]) Get(key K) (V, bool) {
// Retrieve the value for the key from the map.
val, ok := om.values[key]
return val, ok
}
// Delete removes the key-value pair associated with the given key from the ordered map.
func (om *OrderedMap[K, V]) Delete(key K) {
// Iterate over the keys slice to find the key to delete.
for i, k := range om.keys {
// When the key is found, remove it from the slice.
if k == key {
om.keys = append(om.keys[:i], om.keys[i+1:]...)
break
}
}
// Remove the key-value pair from the map.
delete(om.values, key)
}
// Keys returns all keys of the ordered map in order of their insertion.
func (om *OrderedMap[K, V]) Keys() []K {
return om.keys
}
// Values returns all values of the ordered map in the order of their corresponding keys' insertion.
func (om *OrderedMap[K, V]) Values() []V {
// Initialize an empty slice to hold the values.
vals := make([]V, 0, len(om.values))
// Iterate over the keys in order and append the corresponding value to the values slice.
for _, key := range om.keys {
vals = append(vals, om.values[key])
}
return vals
}

View File

@@ -1,169 +0,0 @@
/*
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
Copyright (C) ITsysCOM GmbH
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package utils
import (
"crypto/rand"
"reflect"
"testing"
)
func TestOrderedMapSetGetDelete(t *testing.T) {
testCases := []struct {
key string
value string
}{
{"shortKey", "shortValue"},
{"longKeylongKeylongKeylongKeylongKeylongKey", "longValuelongValuelongValuelongValuelongValue"},
{"keyWithSpecialCharacters!@#$%^&*()", "valueWithSpecialCharacters!@#$%^&*()"},
{"", ""},
}
for _, tc := range testCases {
// Initialize a new OrderedMap for each test case
om := NewOrderedMap[string, string]()
// Perform a set and a get for the initial key-value pair
om.Set(tc.key, tc.value)
val, ok := om.Get(tc.key)
if !ok || val != tc.value {
t.Errorf("Set key-value pair did not match Get result: expected %s, got %s", tc.value, val)
}
// Update the value
newValue := tc.value + "updated"
om.Set(tc.key, newValue)
val, ok = om.Get(tc.key)
if !ok || val != newValue {
t.Errorf("Updated key-value pair did not match Get result: expected %s, got %s", newValue, val)
}
// Delete the key
om.Delete(tc.key)
_, ok = om.Get(tc.key)
if ok {
t.Errorf("Deleted key was still found in map")
}
// Try to get a non-existent key
_, ok = om.Get("non-existent key")
if ok {
t.Errorf("Non-existent key was found in map")
}
}
}
func TestOrderedMapKeysValues(t *testing.T) {
// Initialize a new OrderedMap
om := NewOrderedMap[string, string]()
// Set multiple key-value pairs
om.Set("key1", "value1")
om.Set("key2", "value2")
om.Set("key3", "value3")
// Get the keys and values
keys := om.Keys()
values := om.Values()
// Check the keys
expectedKeys := []string{"key1", "key2", "key3"}
if !reflect.DeepEqual(keys, expectedKeys) {
t.Errorf("Keys do not match expected keys: expected %v, received %v", expectedKeys, keys)
}
// Check the values
expectedValues := []string{"value1", "value2", "value3"}
if !reflect.DeepEqual(values, expectedValues) {
t.Errorf("Values do not match expected values: expected %v, received %v", expectedValues, values)
}
}
// Benchmark that emphasizes the difference in performance for simple values between
// OrderedNavigableMap and the generic OrderedMap.
// Sample usage: go test -bench=. -run=Benchmark_NavigableMaps -benchtime=5s -count 3 -benchmem
func BenchmarkOrderedMaps(b *testing.B) {
letterBytes := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
// Function to generate a random string of `strLen` length
randomString := func(strLen int) string {
byt := make([]byte, strLen)
rand.Read(byt)
for i := range byt {
byt[i] = letterBytes[byt[i]%byte(len(letterBytes))]
}
return string(byt)
}
// Function to generate a slice of n random strings
generateStringSlice := func(n int) []string {
randStrings := make([]string, n)
for i := range randStrings {
randStrings[i] = randomString(10)
}
return randStrings
}
keys := generateStringSlice(100000)
values := generateStringSlice(100000)
b.Run("Generic ordered map - Set", func(b *testing.B) {
genericOm := NewOrderedMap[string, string]()
b.ResetTimer()
for i := 0; i < b.N; i++ {
genericOm.Set(keys[i%len(keys)], values[i%len(values)])
}
})
b.Run("Generic ordered map - Get", func(b *testing.B) {
genericOm := NewOrderedMap[string, string]()
for i := 0; i < len(keys); i++ {
genericOm.Set(keys[i], values[i])
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = genericOm.Get(keys[i%len(keys)])
}
})
b.Run("OrderedNavigableMap - Set", func(b *testing.B) {
onm := NewOrderedNavigableMap()
b.ResetTimer()
for i := 0; i < b.N; i++ {
onm.Set(&FullPath{
Path: keys[i%len(keys)],
PathItems: NewPathItems([]string{keys[i%len(keys)]}),
}, NewNMData(values[i%len(values)]))
}
})
b.Run("OrderedNavigableMap - Field+String", func(b *testing.B) {
onm := NewOrderedNavigableMap()
for i := 0; i < len(keys); i++ {
onm.Set(&FullPath{
Path: keys[i],
PathItems: NewPathItems([]string{keys[i]}),
}, NewNMData(values[i%len(values)]))
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
val, _ := onm.Field(NewPathItems([]string{keys[i%len(keys)]}))
_ = val.String()
}
})
}