mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-15 10:12:29 +08:00
feat: add Set data structure
This commit is contained in:
105
datastructure/set.go
Normal file
105
datastructure/set.go
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
package datastructure
|
||||||
|
|
||||||
|
// Set is a data container, like slice, but element of set is not duplicate
|
||||||
|
type Set[T comparable] map[T]bool
|
||||||
|
|
||||||
|
// NewSet return a instance of set
|
||||||
|
func NewSet[T comparable](values ...T) Set[T] {
|
||||||
|
set := make(Set[T])
|
||||||
|
set.Add(values...)
|
||||||
|
return set
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add value to set
|
||||||
|
func (s Set[T]) Add(values ...T) {
|
||||||
|
for _, v := range values {
|
||||||
|
s[v] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contain checks if set contains value or not
|
||||||
|
func (s Set[T]) Contain(value T) bool {
|
||||||
|
_, ok := s[value]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contain checks if set contains other set
|
||||||
|
func (s Set[T]) ContainAll(other Set[T]) bool {
|
||||||
|
for k := range other {
|
||||||
|
_, ok := s[k]
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone return a copy of set
|
||||||
|
func (s Set[T]) Clone() Set[T] {
|
||||||
|
set := NewSet[T]()
|
||||||
|
set.Add(s.Values()...)
|
||||||
|
return set
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete value of set
|
||||||
|
func (s Set[T]) Delete(values ...T) {
|
||||||
|
for _, v := range values {
|
||||||
|
delete(s, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal checks if two set has same elements or not
|
||||||
|
func (s Set[T]) Equal(other Set[T]) bool {
|
||||||
|
if s.Size() != other.Size() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.ContainAll(other) && other.ContainAll(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate call function by every element of set
|
||||||
|
func (s Set[T]) Iterate(fn func(value T)) {
|
||||||
|
for v := range s {
|
||||||
|
fn(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmpty checks the set is empty or not
|
||||||
|
func (s Set[T]) IsEmpty() bool {
|
||||||
|
return len(s) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size get the number of elements in set
|
||||||
|
func (s Set[T]) Size() int {
|
||||||
|
return len(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Values return all values of set
|
||||||
|
func (s Set[T]) Values() []T {
|
||||||
|
values := make([]T, 0, 0)
|
||||||
|
|
||||||
|
s.Iterate(func(value T) {
|
||||||
|
values = append(values, value)
|
||||||
|
})
|
||||||
|
|
||||||
|
return values
|
||||||
|
}
|
||||||
|
|
||||||
|
// Union creates a new set contain all element of set s and other
|
||||||
|
func (s Set[T]) Union(other Set[T]) Set[T] {
|
||||||
|
set := s.Clone()
|
||||||
|
set.Add(other.Values()...)
|
||||||
|
return set
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intersection creates a new set whose element both be contained in set s and other
|
||||||
|
func (s Set[T]) Intersection(other Set[T]) Set[T] {
|
||||||
|
set := NewSet[T]()
|
||||||
|
s.Iterate(func(value T) {
|
||||||
|
if other.Contain(value) {
|
||||||
|
set.Add(value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return set
|
||||||
|
}
|
||||||
129
datastructure/set_test.go
Normal file
129
datastructure/set_test.go
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
package datastructure
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSet_Add(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestSet_Add")
|
||||||
|
|
||||||
|
set := NewSet[int]()
|
||||||
|
set.Add(1, 2, 3)
|
||||||
|
|
||||||
|
expected := NewSet(1, 2, 3)
|
||||||
|
|
||||||
|
assert.Equal(true, set.Equal(expected))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSet_Contain(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestSet_Contain")
|
||||||
|
|
||||||
|
set := NewSet[int]()
|
||||||
|
set.Add(1, 2, 3)
|
||||||
|
|
||||||
|
assert.Equal(true, set.Contain(1))
|
||||||
|
assert.Equal(false, set.Contain(4))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSet_ContainAll(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestSet_ContainAll")
|
||||||
|
|
||||||
|
set1 := NewSet(1, 2, 3)
|
||||||
|
set2 := NewSet(1, 2)
|
||||||
|
set3 := NewSet(1, 2, 3, 4)
|
||||||
|
|
||||||
|
assert.Equal(true, set1.ContainAll(set2))
|
||||||
|
assert.Equal(false, set1.ContainAll(set3))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSet_Clone(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestSet_Clone")
|
||||||
|
|
||||||
|
set1 := NewSet(1, 2, 3)
|
||||||
|
set2 := set1.Clone()
|
||||||
|
|
||||||
|
assert.Equal(true, set1.Size() == set2.Size())
|
||||||
|
assert.Equal(true, set1.ContainAll(set2))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSet_Delete(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestSet_Delete")
|
||||||
|
|
||||||
|
set := NewSet[int]()
|
||||||
|
set.Add(1, 2, 3)
|
||||||
|
set.Delete(3)
|
||||||
|
|
||||||
|
expected := NewSet(1, 2)
|
||||||
|
|
||||||
|
assert.Equal(true, set.Equal(expected))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSet_Equal(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestSet_Equal")
|
||||||
|
|
||||||
|
set1 := NewSet(1, 2, 3)
|
||||||
|
set2 := NewSet(1, 2, 3)
|
||||||
|
set3 := NewSet(1, 2, 3, 4)
|
||||||
|
|
||||||
|
assert.Equal(true, set1.Equal(set2))
|
||||||
|
assert.Equal(false, set1.Equal(set3))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSet_Iterate(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestSet_Iterate")
|
||||||
|
|
||||||
|
set := NewSet(1, 2, 3)
|
||||||
|
arr := []int{}
|
||||||
|
set.Iterate(func(value int) {
|
||||||
|
arr = append(arr, value)
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Equal(3, len(arr))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSet_IsEmpty(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestSet_IsEmpty")
|
||||||
|
|
||||||
|
set := NewSet[int]()
|
||||||
|
assert.Equal(true, set.IsEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSet_Size(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestSet_Size")
|
||||||
|
|
||||||
|
set := NewSet(1, 2, 3)
|
||||||
|
assert.Equal(3, set.Size())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSet_Values(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestSet_Values")
|
||||||
|
|
||||||
|
set := NewSet(1, 2, 3)
|
||||||
|
values := set.Values()
|
||||||
|
|
||||||
|
assert.Equal(3, len(values))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSet_Union(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestSet_Union")
|
||||||
|
|
||||||
|
set1 := NewSet(1, 2, 3)
|
||||||
|
set2 := NewSet(2, 3, 4, 5)
|
||||||
|
expected := NewSet(1, 2, 3, 4, 5)
|
||||||
|
unionSet := set1.Union(set2)
|
||||||
|
|
||||||
|
assert.Equal(expected, unionSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSet_Intersection(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestSet_Intersection")
|
||||||
|
|
||||||
|
set1 := NewSet(1, 2, 3)
|
||||||
|
set2 := NewSet(2, 3, 4, 5)
|
||||||
|
expected := NewSet(2, 3)
|
||||||
|
intersectionSet := set1.Intersection(set2)
|
||||||
|
|
||||||
|
assert.Equal(expected, intersectionSet)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user