Skip to content

feat: add set implementation using generic #656

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,7 @@ Read our [Contribution Guidelines](CONTRIBUTING.md) before you contribute.

---

##### package set implements a Set using a golang map. This implies that only the types that are accepted as valid map keys can be used as set elements. For instance, do not try to Add a slice, or the program will panic.
##### package set implements a Set using generics and a golang map with comparable interface key. This implies that only the types that are accepted as valid map keys can be used as set elements

---
##### Functions:
Expand Down
78 changes: 39 additions & 39 deletions structure/set/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
package set

// New gives new set.
func New(items ...any) Set {
st := set{
elements: make(map[any]bool),
func New[T comparable](items ...T) Set[T] {
st := set[T]{
elements: make(map[T]bool),
}
for _, item := range items {
st.Add(item)
Expand All @@ -15,73 +15,73 @@ func New(items ...any) Set {
}

// Set is an interface of possible methods on 'set'.
type Set interface {
type Set[T comparable] interface {
// Add: adds new element to the set
Add(item any)
Add(item T)
// Delete: deletes the passed element from the set if present
Delete(item any)
Delete(item T)
// Len: gives the length of the set (total no. of elements in set)
Len() int
// GetItems: gives the array( []any ) of elements of the set.
GetItems() []any
// GetItems: gives the array( []T ) of elements of the set.
GetItems() []T
// In: checks whether item is present in set or not.
In(item any) bool
In(item T) bool
// IsSubsetOf: checks whether set is subset of set2 or not.
IsSubsetOf(set2 Set) bool
IsSubsetOf(set2 Set[T]) bool
// IsProperSubsetOf: checks whether set is proper subset of set2 or not.
// ex: [1,2,3] proper subset of [1,2,3,4] -> true
IsProperSubsetOf(set2 Set) bool
IsProperSubsetOf(set2 Set[T]) bool
// IsSupersetOf: checks whether set is superset of set2 or not.
IsSupersetOf(set2 Set) bool
IsSupersetOf(set2 Set[T]) bool
// IsProperSupersetOf: checks whether set is proper superset of set2 or not.
// ex: [1,2,3,4] proper superset of [1,2,3] -> true
IsProperSupersetOf(set2 Set) bool
IsProperSupersetOf(set2 Set[T]) bool
// Union: gives new union set of both sets.
// ex: [1,2,3] union [3,4,5] -> [1,2,3,4,5]
Union(set2 Set) Set
Union(set2 Set[T]) Set[T]
// Intersection: gives new intersection set of both sets.
// ex: [1,2,3] Intersection [3,4,5] -> [3]
Intersection(set2 Set) Set
Intersection(set2 Set[T]) Set[T]
// Difference: gives new difference set of both sets.
// ex: [1,2,3] Difference [3,4,5] -> [1,2]
Difference(set2 Set) Set
Difference(set2 Set[T]) Set[T]
// SymmetricDifference: gives new symmetric difference set of both sets.
// ex: [1,2,3] SymmetricDifference [3,4,5] -> [1,2,4,5]
SymmetricDifference(set2 Set) Set
SymmetricDifference(set2 Set[T]) Set[T]
}

type set struct {
elements map[any]bool
type set[T comparable] struct {
elements map[T]bool
}

func (st *set) Add(value any) {
func (st *set[T]) Add(value T) {
st.elements[value] = true
}

func (st *set) Delete(value any) {
func (st *set[T]) Delete(value T) {
delete(st.elements, value)
}

func (st *set) GetItems() []any {
keys := make([]any, 0, len(st.elements))
func (st *set[T]) GetItems() []T {
keys := make([]T, 0, len(st.elements))
for k := range st.elements {
keys = append(keys, k)
}
return keys
}

func (st *set) Len() int {
func (st *set[T]) Len() int {
return len(st.elements)
}

func (st *set) In(value any) bool {
func (st *set[T]) In(value T) bool {
if _, in := st.elements[value]; in {
return true
}
return false
}

func (st *set) IsSubsetOf(superSet Set) bool {
func (st *set[T]) IsSubsetOf(superSet Set[T]) bool {
if st.Len() > superSet.Len() {
return false
}
Expand All @@ -94,26 +94,26 @@ func (st *set) IsSubsetOf(superSet Set) bool {
return true
}

func (st *set) IsProperSubsetOf(superSet Set) bool {
func (st *set[T]) IsProperSubsetOf(superSet Set[T]) bool {
if st.Len() == superSet.Len() {
return false
}
return st.IsSubsetOf(superSet)
}

func (st *set) IsSupersetOf(subSet Set) bool {
func (st *set[T]) IsSupersetOf(subSet Set[T]) bool {
return subSet.IsSubsetOf(st)
}

func (st *set) IsProperSupersetOf(subSet Set) bool {
func (st *set[T]) IsProperSupersetOf(subSet Set[T]) bool {
if st.Len() == subSet.Len() {
return false
}
return st.IsSupersetOf(subSet)
}

func (st *set) Union(st2 Set) Set {
unionSet := New()
func (st *set[T]) Union(st2 Set[T]) Set[T] {
unionSet := New[T]()
for _, item := range st.GetItems() {
unionSet.Add(item)
}
Expand All @@ -123,9 +123,9 @@ func (st *set) Union(st2 Set) Set {
return unionSet
}

func (st *set) Intersection(st2 Set) Set {
intersectionSet := New()
var minSet, maxSet Set
func (st *set[T]) Intersection(st2 Set[T]) Set[T] {
intersectionSet := New[T]()
var minSet, maxSet Set[T]
if st.Len() > st2.Len() {
minSet = st2
maxSet = st
Expand All @@ -141,8 +141,8 @@ func (st *set) Intersection(st2 Set) Set {
return intersectionSet
}

func (st *set) Difference(st2 Set) Set {
differenceSet := New()
func (st *set[T]) Difference(st2 Set[T]) Set[T] {
differenceSet := New[T]()
for _, item := range st.GetItems() {
if !st2.In(item) {
differenceSet.Add(item)
Expand All @@ -151,9 +151,9 @@ func (st *set) Difference(st2 Set) Set {
return differenceSet
}

func (st *set) SymmetricDifference(st2 Set) Set {
symmetricDifferenceSet := New()
dropSet := New()
func (st *set[T]) SymmetricDifference(st2 Set[T]) Set[T] {
symmetricDifferenceSet := New[T]()
dropSet := New[T]()
for _, item := range st.GetItems() {
if st2.In(item) {
dropSet.Add(item)
Expand Down
30 changes: 15 additions & 15 deletions structure/set/set_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,9 @@ func TestIsProperSupersetOf(t *testing.T) {
func TestUnion(t *testing.T) {
td := []struct {
name string
s1 Set
s2 Set
expSet Set
s1 Set[int]
s2 Set[int]
expSet Set[int]
}{
{"union of different sets", New(1, 2, 3), New(4, 5, 6), New(1, 2, 3, 4, 5, 6)},
{"union of sets with elements in common", New(1, 2, 3), New(1, 2, 4), New(1, 2, 3, 4)},
Expand All @@ -144,11 +144,11 @@ func TestUnion(t *testing.T) {
func TestIntersection(t *testing.T) {
td := []struct {
name string
s1 Set
s2 Set
expSet Set
s1 Set[int]
s2 Set[int]
expSet Set[int]
}{
{"intersection of different sets", New(0, 1, 2, 3), New(4, 5, 6), New()},
{"intersection of different sets", New(0, 1, 2, 3), New(4, 5, 6), New[int]()},
{"intersection of sets with elements in common", New(1, 2, 3), New(1, 2, 4), New(1, 2)},
{"intersection of same sets", New(1, 2, 3), New(1, 2, 3), New(1, 2, 3)},
}
Expand All @@ -170,13 +170,13 @@ func TestIntersection(t *testing.T) {
func TestDifference(t *testing.T) {
td := []struct {
name string
s1 Set
s2 Set
expSet Set
s1 Set[int]
s2 Set[int]
expSet Set[int]
}{
{"difference of different sets", New(1, 2, 3), New(4, 5, 6), New(1, 2, 3)},
{"difference of sets with elements in common", New(1, 2, 3), New(1, 2, 4), New(3)},
{"difference of same sets", New(1, 2, 3), New(1, 2, 3), New()},
{"difference of same sets", New(1, 2, 3), New(1, 2, 3), New[int]()},
}
for _, tc := range td {
t.Run(tc.name, func(t *testing.T) {
Expand All @@ -196,13 +196,13 @@ func TestDifference(t *testing.T) {
func TestSymmetricDifference(t *testing.T) {
td := []struct {
name string
s1 Set
s2 Set
expSet Set
s1 Set[int]
s2 Set[int]
expSet Set[int]
}{
{"symmetric difference of different sets", New(1, 2, 3), New(4, 5, 6), New(1, 2, 3, 4, 5, 6)},
{"symmetric difference of sets with elements in common", New(1, 2, 3), New(1, 2, 4), New(3, 4)},
{"symmetric difference of same sets", New(1, 2, 3), New(1, 2, 3), New()},
{"symmetric difference of same sets", New(1, 2, 3), New(1, 2, 3), New[int]()},
}
for _, tc := range td {
t.Run(tc.name, func(t *testing.T) {
Expand Down