Skip to content

Commit

Permalink
Merge pull request #12 from matthyx/main
Browse files Browse the repository at this point in the history
modify Delete method to return deleted value
  • Loading branch information
spekary authored Nov 9, 2024
2 parents fff85b2 + acbfc27 commit 98d8666
Show file tree
Hide file tree
Showing 12 changed files with 54 additions and 35 deletions.
16 changes: 9 additions & 7 deletions map.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ package maps
//
// The recommended way to create a Map is to first declare a concrete type alias, and then call
// new on it, like this:
// type MyMap = Map[string,int]
//
// m := new(MyMap)
// type MyMap = Map[string,int]
//
// m := new(MyMap)
//
// This will allow you to swap in a different kind of Map just by changing the type.
type Map[K comparable, V any] struct {
Expand Down Expand Up @@ -48,8 +49,8 @@ func (m Map[K, V]) Has(k K) bool {
}

// Delete removes the key from the map. If the key does not exist, nothing happens.
func (m Map[K, V]) Delete(k K) {
m.items.Delete(k)
func (m Map[K, V]) Delete(k K) V {
return m.items.Delete(k)
}

// Keys returns a new slice containing the keys of the map.
Expand Down Expand Up @@ -95,9 +96,10 @@ func (m Map[K, V]) MarshalBinary() ([]byte, error) {
// UnmarshalBinary implements the BinaryUnmarshaler interface to convert a byte stream to a Map.
//
// Note that you may need to register the map at init time with gob like this:
// func init() {
// gob.Register(new(Map[keytype,valuetype]))
// }
//
// func init() {
// gob.Register(new(Map[keytype,valuetype]))
// }
func (m *Map[K, V]) UnmarshalBinary(data []byte) (err error) {
return m.items.UnmarshalBinary(data)
}
Expand Down
2 changes: 1 addition & 1 deletion mapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type MapI[K comparable, V any] interface {
Values() []V
Merge(MapI[K, V])
Equal(MapI[K, V]) bool
Delete(k K)
Delete(k K) (v V)
}

// Setter sets a value in a map.
Expand Down
12 changes: 8 additions & 4 deletions mapi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import (
"bytes"
"encoding/gob"
"encoding/json"
"github.com/stretchr/testify/assert"
"testing"

"github.com/stretchr/testify/assert"
)

type makeF func(sources ...mapT) MapI[string, int]
Expand Down Expand Up @@ -243,14 +244,17 @@ func testUnmarshalJSON[M any](t *testing.T, f makeF) {
func testDelete(t *testing.T, f makeF) {
t.Run("Delete", func(t *testing.T) {
m := f(mapT{"a": 1, "b": 2})
m.Delete("a")
v := m.Delete("a")

assert.Equal(t, 1, v)
assert.False(t, m.Has("a"))
assert.True(t, m.Has("b"))

m.Delete("b")
v = m.Delete("b")
assert.Equal(t, 2, v)
assert.False(t, m.Has("b"))

m.Delete("b") // make sure deleting from an empty map is a no-op
v = m.Delete("b") // make sure deleting from an empty map is a no-op
assert.Equal(t, 0, v)
})
}
7 changes: 4 additions & 3 deletions safe_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,12 @@ func (m *SafeMap[K, V]) Load(k K) (v V, ok bool) {
return
}

// Delete removes the key from the map. If the key does not exist, nothing happens.
func (m *SafeMap[K, V]) Delete(k K) {
// Delete removes the key from the map and returns the value. If the key does not exist, the zero value will be returned.
func (m *SafeMap[K, V]) Delete(k K) (v V) {
m.Lock()
m.items.Delete(k)
v = m.items.Delete(k)
m.Unlock()
return
}

// Values returns a slice of the values. It will return a nil slice if the map is empty.
Expand Down
3 changes: 2 additions & 1 deletion safe_map_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ package maps
import (
"encoding/gob"
"fmt"
"github.com/stretchr/testify/assert"
"testing"

"github.com/stretchr/testify/assert"
)

func TestSafeMap_Mapi(t *testing.T) {
Expand Down
9 changes: 5 additions & 4 deletions safe_slice_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,14 +125,14 @@ func (m *SafeSliceMap[K, V]) SetAt(index int, key K, val V) {
m.Unlock()
}

// Delete removes the item with the given key.
func (m *SafeSliceMap[K, V]) Delete(key K) {
// Delete removes the item with the given key and returns the value.
func (m *SafeSliceMap[K, V]) Delete(key K) (val V) {
m.Lock()
if _, ok := m.items[key]; ok {
val = m.items[key]
if m.lessF != nil {
oldVal := m.items[key]
loc := sort.Search(len(m.items), func(n int) bool {
return !m.lessF(m.order[n], key, m.items[m.order[n]], oldVal)
return !m.lessF(m.order[n], key, m.items[m.order[n]], val)
})
m.order = append(m.order[:loc], m.order[loc+1:]...)
} else {
Expand All @@ -146,6 +146,7 @@ func (m *SafeSliceMap[K, V]) Delete(key K) {
delete(m.items, key)
}
m.Unlock()
return
}

// Get returns the value based on its key. If the key does not exist, an empty value is returned.
Expand Down
3 changes: 2 additions & 1 deletion safe_slice_map_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ package maps
import (
"encoding/gob"
"fmt"
"github.com/stretchr/testify/assert"
"testing"

"github.com/stretchr/testify/assert"
)

func TestSafeSliceMap_Mapi(t *testing.T) {
Expand Down
3 changes: 2 additions & 1 deletion seti_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import (
"bytes"
"encoding/gob"
"encoding/json"
"github.com/stretchr/testify/assert"
"testing"

"github.com/stretchr/testify/assert"
)

type makeSetF func(sources ...string) SetI[string]
Expand Down
9 changes: 5 additions & 4 deletions slice_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,17 +128,17 @@ func (m *SliceMap[K, V]) SetAt(index int, key K, val V) {
m.items[key] = val
}

// Delete removes the item with the given key.
func (m *SliceMap[K, V]) Delete(key K) {
// Delete removes the key from the map and returns the value. If the key does not exist, the zero value will be returned.
func (m *SliceMap[K, V]) Delete(key K) (val V) {
if m == nil {
return
}

if _, ok := m.items[key]; ok {
val = m.items[key]
if m.lessF != nil {
oldVal := m.items[key]
loc := sort.Search(len(m.items), func(n int) bool {
return !m.lessF(m.order[n], key, m.items[m.order[n]], oldVal)
return !m.lessF(m.order[n], key, m.items[m.order[n]], val)
})
m.order = append(m.order[:loc], m.order[loc+1:]...)
} else {
Expand All @@ -151,6 +151,7 @@ func (m *SliceMap[K, V]) Delete(key K) {
}
delete(m.items, key)
}
return
}

// Get returns the value based on its key. If the key does not exist, an empty value is returned.
Expand Down
3 changes: 2 additions & 1 deletion slice_map_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ package maps
import (
"encoding/gob"
"fmt"
"github.com/stretchr/testify/assert"
"testing"

"github.com/stretchr/testify/assert"
)

func TestSliceMap_Mapi(t *testing.T) {
Expand Down
19 changes: 12 additions & 7 deletions std_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import (
//
// The zero value is NOT settable. Use NewStdMap to create a new StdMap object, or use standard
// map instantiation syntax like this:
// m := StdMap[string, int]{"a":1}
//
// m := StdMap[string, int]{"a":1}
//
// StdMap is mostly a convenience type for making a standard Go map into a MapI interface.
// Generally, you should use Map instead, as it presents a consistent interface that allows you
Expand All @@ -22,7 +23,8 @@ type StdMap[K comparable, V any] map[K]V
// NewStdMap creates a new map that maps values of type K to values of type V.
// Pass in zero or more standard maps and the contents of those maps will be copied to the new StdMap.
// You can also create a new StdMap like this:
// m := StdMap[string, int]{"a":1}
//
// m := StdMap[string, int]{"a":1}
func NewStdMap[K comparable, V any](sources ...map[K]V) StdMap[K, V] {
m := StdMap[K, V]{}
for _, i := range sources {
Expand Down Expand Up @@ -103,9 +105,11 @@ func (m StdMap[K, V]) Set(k K, v V) {
m[k] = v
}

// Delete removes the key from the map. If the key does not exist, nothing happens.
func (m StdMap[K, V]) Delete(k K) {
// Delete removes the key from the map and returns the value. If the key does not exist, the zero value will be returned.
func (m StdMap[K, V]) Delete(k K) (v V) {
v, _ = m.Load(k)
delete(m, k)
return
}

// Keys returns a new slice containing the keys of the map.
Expand Down Expand Up @@ -176,9 +180,10 @@ func (m StdMap[K, V]) MarshalBinary() ([]byte, error) {
// UnmarshalBinary implements the BinaryUnmarshaler interface to convert a byte stream to a Map.
//
// Note that you will likely need to register the unmarshaller at init time with gob like this:
// func init() {
// gob.Register(new(Map[K,V]))
// }
//
// func init() {
// gob.Register(new(Map[K,V]))
// }
func (m *StdMap[K, V]) UnmarshalBinary(data []byte) (err error) {
b := bytes.NewBuffer(data)
dec := gob.NewDecoder(b)
Expand Down
3 changes: 2 additions & 1 deletion std_map_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ package maps
import (
"encoding/gob"
"fmt"
"github.com/stretchr/testify/assert"
"testing"

"github.com/stretchr/testify/assert"
)

type mapT = StdMap[string, int]
Expand Down

0 comments on commit 98d8666

Please sign in to comment.