Removing all temp *Generic based names by swapping with the original names to minimize changes
This commit is contained in:
parent
cd0ae61739
commit
1658d57751
240
bench_test.go
240
bench_test.go
|
@ -46,7 +46,7 @@ func toInterfaces(i []int) []interface{} {
|
|||
return ifs
|
||||
}
|
||||
|
||||
func benchAdd(b *testing.B, s SetGeneric[int]) {
|
||||
func benchAdd(b *testing.B, s Set[int]) {
|
||||
nums := nrand(b.N)
|
||||
b.ResetTimer()
|
||||
for _, v := range nums {
|
||||
|
@ -55,14 +55,14 @@ func benchAdd(b *testing.B, s SetGeneric[int]) {
|
|||
}
|
||||
|
||||
func BenchmarkAddSafe(b *testing.B) {
|
||||
benchAdd(b, NewSetGeneric[int]())
|
||||
benchAdd(b, NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkAddUnsafe(b *testing.B) {
|
||||
benchAdd(b, NewThreadUnsafeSetGeneric[int]())
|
||||
benchAdd(b, NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func benchRemove(b *testing.B, s SetGeneric[int]) {
|
||||
func benchRemove(b *testing.B, s Set[int]) {
|
||||
nums := nrand(b.N)
|
||||
for _, v := range nums {
|
||||
s.Add(v)
|
||||
|
@ -75,28 +75,28 @@ func benchRemove(b *testing.B, s SetGeneric[int]) {
|
|||
}
|
||||
|
||||
func BenchmarkRemoveSafe(b *testing.B) {
|
||||
benchRemove(b, NewSetGeneric[int]())
|
||||
benchRemove(b, NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkRemoveUnsafe(b *testing.B) {
|
||||
benchRemove(b, NewThreadUnsafeSetGeneric[int]())
|
||||
benchRemove(b, NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func benchCardinality(b *testing.B, s SetGeneric[int]) {
|
||||
func benchCardinality(b *testing.B, s Set[int]) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
s.Cardinality()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCardinalitySafe(b *testing.B) {
|
||||
benchCardinality(b, NewSetGeneric[int]())
|
||||
benchCardinality(b, NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkCardinalityUnsafe(b *testing.B) {
|
||||
benchCardinality(b, NewThreadUnsafeSetGeneric[int]())
|
||||
benchCardinality(b, NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func benchClear(b *testing.B, s SetGeneric[int]) {
|
||||
func benchClear(b *testing.B, s Set[int]) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
s.Clear()
|
||||
|
@ -104,14 +104,14 @@ func benchClear(b *testing.B, s SetGeneric[int]) {
|
|||
}
|
||||
|
||||
func BenchmarkClearSafe(b *testing.B) {
|
||||
benchClear(b, NewSetGeneric[int]())
|
||||
benchClear(b, NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkClearUnsafe(b *testing.B) {
|
||||
benchClear(b, NewThreadUnsafeSetGeneric[int]())
|
||||
benchClear(b, NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func benchClone(b *testing.B, n int, s SetGeneric[int]) {
|
||||
func benchClone(b *testing.B, n int, s Set[int]) {
|
||||
nums := nrand(n)
|
||||
for _, v := range nums {
|
||||
s.Add(v)
|
||||
|
@ -124,30 +124,30 @@ func benchClone(b *testing.B, n int, s SetGeneric[int]) {
|
|||
}
|
||||
|
||||
func BenchmarkClone1Safe(b *testing.B) {
|
||||
benchClone(b, 1, NewSetGeneric[int]())
|
||||
benchClone(b, 1, NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkClone1Unsafe(b *testing.B) {
|
||||
benchClone(b, 1, NewThreadUnsafeSetGeneric[int]())
|
||||
benchClone(b, 1, NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkClone10Safe(b *testing.B) {
|
||||
benchClone(b, 10, NewSetGeneric[int]())
|
||||
benchClone(b, 10, NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkClone10Unsafe(b *testing.B) {
|
||||
benchClone(b, 10, NewThreadUnsafeSetGeneric[int]())
|
||||
benchClone(b, 10, NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkClone100Safe(b *testing.B) {
|
||||
benchClone(b, 100, NewSetGeneric[int]())
|
||||
benchClone(b, 100, NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkClone100Unsafe(b *testing.B) {
|
||||
benchClone(b, 100, NewThreadUnsafeSetGeneric[int]())
|
||||
benchClone(b, 100, NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func benchContains(b *testing.B, n int, s SetGeneric[int]) {
|
||||
func benchContains(b *testing.B, n int, s Set[int]) {
|
||||
nums := nrand(n)
|
||||
for _, v := range nums {
|
||||
s.Add(v)
|
||||
|
@ -162,30 +162,30 @@ func benchContains(b *testing.B, n int, s SetGeneric[int]) {
|
|||
}
|
||||
|
||||
func BenchmarkContains1Safe(b *testing.B) {
|
||||
benchContains(b, 1, NewSetGeneric[int]())
|
||||
benchContains(b, 1, NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkContains1Unsafe(b *testing.B) {
|
||||
benchContains(b, 1, NewThreadUnsafeSetGeneric[int]())
|
||||
benchContains(b, 1, NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkContains10Safe(b *testing.B) {
|
||||
benchContains(b, 10, NewSetGeneric[int]())
|
||||
benchContains(b, 10, NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkContains10Unsafe(b *testing.B) {
|
||||
benchContains(b, 10, NewThreadUnsafeSetGeneric[int]())
|
||||
benchContains(b, 10, NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkContains100Safe(b *testing.B) {
|
||||
benchContains(b, 100, NewSetGeneric[int]())
|
||||
benchContains(b, 100, NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkContains100Unsafe(b *testing.B) {
|
||||
benchContains(b, 100, NewThreadUnsafeSetGeneric[int]())
|
||||
benchContains(b, 100, NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func benchEqual(b *testing.B, n int, s, t SetGeneric[int]) {
|
||||
func benchEqual(b *testing.B, n int, s, t Set[int]) {
|
||||
nums := nrand(n)
|
||||
for _, v := range nums {
|
||||
s.Add(v)
|
||||
|
@ -199,30 +199,30 @@ func benchEqual(b *testing.B, n int, s, t SetGeneric[int]) {
|
|||
}
|
||||
|
||||
func BenchmarkEqual1Safe(b *testing.B) {
|
||||
benchEqual(b, 1, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchEqual(b, 1, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkEqual1Unsafe(b *testing.B) {
|
||||
benchEqual(b, 1, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchEqual(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkEqual10Safe(b *testing.B) {
|
||||
benchEqual(b, 10, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchEqual(b, 10, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkEqual10Unsafe(b *testing.B) {
|
||||
benchEqual(b, 10, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchEqual(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkEqual100Safe(b *testing.B) {
|
||||
benchEqual(b, 100, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchEqual(b, 100, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkEqual100Unsafe(b *testing.B) {
|
||||
benchEqual(b, 100, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchEqual(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func benchDifference(b *testing.B, n int, s, t SetGeneric[int]) {
|
||||
func benchDifference(b *testing.B, n int, s, t Set[int]) {
|
||||
nums := nrand(n)
|
||||
for _, v := range nums {
|
||||
s.Add(v)
|
||||
|
@ -237,7 +237,7 @@ func benchDifference(b *testing.B, n int, s, t SetGeneric[int]) {
|
|||
}
|
||||
}
|
||||
|
||||
func benchIsSubset(b *testing.B, n int, s, t SetGeneric[int]) {
|
||||
func benchIsSubset(b *testing.B, n int, s, t Set[int]) {
|
||||
nums := nrand(n)
|
||||
for _, v := range nums {
|
||||
s.Add(v)
|
||||
|
@ -251,30 +251,30 @@ func benchIsSubset(b *testing.B, n int, s, t SetGeneric[int]) {
|
|||
}
|
||||
|
||||
func BenchmarkIsSubset1Safe(b *testing.B) {
|
||||
benchIsSubset(b, 1, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchIsSubset(b, 1, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIsSubset1Unsafe(b *testing.B) {
|
||||
benchIsSubset(b, 1, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchIsSubset(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIsSubset10Safe(b *testing.B) {
|
||||
benchIsSubset(b, 10, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchIsSubset(b, 10, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIsSubset10Unsafe(b *testing.B) {
|
||||
benchIsSubset(b, 10, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchIsSubset(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIsSubset100Safe(b *testing.B) {
|
||||
benchIsSubset(b, 100, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchIsSubset(b, 100, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIsSubset100Unsafe(b *testing.B) {
|
||||
benchIsSubset(b, 100, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchIsSubset(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func benchIsSuperset(b *testing.B, n int, s, t SetGeneric[int]) {
|
||||
func benchIsSuperset(b *testing.B, n int, s, t Set[int]) {
|
||||
nums := nrand(n)
|
||||
for _, v := range nums {
|
||||
s.Add(v)
|
||||
|
@ -288,30 +288,30 @@ func benchIsSuperset(b *testing.B, n int, s, t SetGeneric[int]) {
|
|||
}
|
||||
|
||||
func BenchmarkIsSuperset1Safe(b *testing.B) {
|
||||
benchIsSuperset(b, 1, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchIsSuperset(b, 1, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIsSuperset1Unsafe(b *testing.B) {
|
||||
benchIsSuperset(b, 1, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchIsSuperset(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIsSuperset10Safe(b *testing.B) {
|
||||
benchIsSuperset(b, 10, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchIsSuperset(b, 10, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIsSuperset10Unsafe(b *testing.B) {
|
||||
benchIsSuperset(b, 10, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchIsSuperset(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIsSuperset100Safe(b *testing.B) {
|
||||
benchIsSuperset(b, 100, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchIsSuperset(b, 100, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIsSuperset100Unsafe(b *testing.B) {
|
||||
benchIsSuperset(b, 100, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchIsSuperset(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func benchIsProperSubset(b *testing.B, n int, s, t SetGeneric[int]) {
|
||||
func benchIsProperSubset(b *testing.B, n int, s, t Set[int]) {
|
||||
nums := nrand(n)
|
||||
for _, v := range nums {
|
||||
s.Add(v)
|
||||
|
@ -325,30 +325,30 @@ func benchIsProperSubset(b *testing.B, n int, s, t SetGeneric[int]) {
|
|||
}
|
||||
|
||||
func BenchmarkIsProperSubset1Safe(b *testing.B) {
|
||||
benchIsProperSubset(b, 1, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchIsProperSubset(b, 1, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIsProperSubset1Unsafe(b *testing.B) {
|
||||
benchIsProperSubset(b, 1, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchIsProperSubset(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIsProperSubset10Safe(b *testing.B) {
|
||||
benchIsProperSubset(b, 10, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchIsProperSubset(b, 10, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIsProperSubset10Unsafe(b *testing.B) {
|
||||
benchIsProperSubset(b, 10, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchIsProperSubset(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIsProperSubset100Safe(b *testing.B) {
|
||||
benchIsProperSubset(b, 100, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchIsProperSubset(b, 100, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIsProperSubset100Unsafe(b *testing.B) {
|
||||
benchIsProperSubset(b, 100, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchIsProperSubset(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func benchIsProperSuperset(b *testing.B, n int, s, t SetGeneric[int]) {
|
||||
func benchIsProperSuperset(b *testing.B, n int, s, t Set[int]) {
|
||||
nums := nrand(n)
|
||||
for _, v := range nums {
|
||||
s.Add(v)
|
||||
|
@ -362,54 +362,54 @@ func benchIsProperSuperset(b *testing.B, n int, s, t SetGeneric[int]) {
|
|||
}
|
||||
|
||||
func BenchmarkIsProperSuperset1Safe(b *testing.B) {
|
||||
benchIsProperSuperset(b, 1, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchIsProperSuperset(b, 1, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIsProperSuperset1Unsafe(b *testing.B) {
|
||||
benchIsProperSuperset(b, 1, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchIsProperSuperset(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIsProperSuperset10Safe(b *testing.B) {
|
||||
benchIsProperSuperset(b, 10, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchIsProperSuperset(b, 10, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIsProperSuperset10Unsafe(b *testing.B) {
|
||||
benchIsProperSuperset(b, 10, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchIsProperSuperset(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIsProperSuperset100Safe(b *testing.B) {
|
||||
benchIsProperSuperset(b, 100, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchIsProperSuperset(b, 100, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIsProperSuperset100Unsafe(b *testing.B) {
|
||||
benchIsProperSuperset(b, 100, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchIsProperSuperset(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkDifference1Safe(b *testing.B) {
|
||||
benchDifference(b, 1, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchDifference(b, 1, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkDifference1Unsafe(b *testing.B) {
|
||||
benchDifference(b, 1, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchDifference(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkDifference10Safe(b *testing.B) {
|
||||
benchDifference(b, 10, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchDifference(b, 10, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkDifference10Unsafe(b *testing.B) {
|
||||
benchDifference(b, 10, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchDifference(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkDifference100Safe(b *testing.B) {
|
||||
benchDifference(b, 100, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchDifference(b, 100, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkDifference100Unsafe(b *testing.B) {
|
||||
benchDifference(b, 100, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchDifference(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func benchIntersect(b *testing.B, n int, s, t SetGeneric[int]) {
|
||||
func benchIntersect(b *testing.B, n int, s, t Set[int]) {
|
||||
nums := nrand(int(float64(n) * float64(1.5)))
|
||||
for _, v := range nums[:n] {
|
||||
s.Add(v)
|
||||
|
@ -425,30 +425,30 @@ func benchIntersect(b *testing.B, n int, s, t SetGeneric[int]) {
|
|||
}
|
||||
|
||||
func BenchmarkIntersect1Safe(b *testing.B) {
|
||||
benchIntersect(b, 1, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchIntersect(b, 1, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIntersect1Unsafe(b *testing.B) {
|
||||
benchIntersect(b, 1, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchIntersect(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIntersect10Safe(b *testing.B) {
|
||||
benchIntersect(b, 10, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchIntersect(b, 10, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIntersect10Unsafe(b *testing.B) {
|
||||
benchIntersect(b, 10, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchIntersect(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIntersect100Safe(b *testing.B) {
|
||||
benchIntersect(b, 100, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchIntersect(b, 100, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIntersect100Unsafe(b *testing.B) {
|
||||
benchIntersect(b, 100, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchIntersect(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func benchSymmetricDifference(b *testing.B, n int, s, t SetGeneric[int]) {
|
||||
func benchSymmetricDifference(b *testing.B, n int, s, t Set[int]) {
|
||||
nums := nrand(int(float64(n) * float64(1.5)))
|
||||
for _, v := range nums[:n] {
|
||||
s.Add(v)
|
||||
|
@ -464,30 +464,30 @@ func benchSymmetricDifference(b *testing.B, n int, s, t SetGeneric[int]) {
|
|||
}
|
||||
|
||||
func BenchmarkSymmetricDifference1Safe(b *testing.B) {
|
||||
benchSymmetricDifference(b, 1, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchSymmetricDifference(b, 1, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkSymmetricDifference1Unsafe(b *testing.B) {
|
||||
benchSymmetricDifference(b, 1, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchSymmetricDifference(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkSymmetricDifference10Safe(b *testing.B) {
|
||||
benchSymmetricDifference(b, 10, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchSymmetricDifference(b, 10, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkSymmetricDifference10Unsafe(b *testing.B) {
|
||||
benchSymmetricDifference(b, 10, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchSymmetricDifference(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkSymmetricDifference100Safe(b *testing.B) {
|
||||
benchSymmetricDifference(b, 100, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchSymmetricDifference(b, 100, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkSymmetricDifference100Unsafe(b *testing.B) {
|
||||
benchSymmetricDifference(b, 100, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchSymmetricDifference(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func benchUnion(b *testing.B, n int, s, t SetGeneric[int]) {
|
||||
func benchUnion(b *testing.B, n int, s, t Set[int]) {
|
||||
nums := nrand(n)
|
||||
for _, v := range nums[:n/2] {
|
||||
s.Add(v)
|
||||
|
@ -503,30 +503,30 @@ func benchUnion(b *testing.B, n int, s, t SetGeneric[int]) {
|
|||
}
|
||||
|
||||
func BenchmarkUnion1Safe(b *testing.B) {
|
||||
benchUnion(b, 1, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchUnion(b, 1, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkUnion1Unsafe(b *testing.B) {
|
||||
benchUnion(b, 1, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchUnion(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkUnion10Safe(b *testing.B) {
|
||||
benchUnion(b, 10, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchUnion(b, 10, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkUnion10Unsafe(b *testing.B) {
|
||||
benchUnion(b, 10, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchUnion(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkUnion100Safe(b *testing.B) {
|
||||
benchUnion(b, 100, NewSetGeneric[int](), NewSetGeneric[int]())
|
||||
benchUnion(b, 100, NewSet[int](), NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkUnion100Unsafe(b *testing.B) {
|
||||
benchUnion(b, 100, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
|
||||
benchUnion(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func benchEach(b *testing.B, n int, s SetGeneric[int]) {
|
||||
func benchEach(b *testing.B, n int, s Set[int]) {
|
||||
nums := nrand(n)
|
||||
for _, v := range nums {
|
||||
s.Add(v)
|
||||
|
@ -541,30 +541,30 @@ func benchEach(b *testing.B, n int, s SetGeneric[int]) {
|
|||
}
|
||||
|
||||
func BenchmarkEach1Safe(b *testing.B) {
|
||||
benchEach(b, 1, NewSetGeneric[int]())
|
||||
benchEach(b, 1, NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkEach1Unsafe(b *testing.B) {
|
||||
benchEach(b, 1, NewThreadUnsafeSetGeneric[int]())
|
||||
benchEach(b, 1, NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkEach10Safe(b *testing.B) {
|
||||
benchEach(b, 10, NewSetGeneric[int]())
|
||||
benchEach(b, 10, NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkEach10Unsafe(b *testing.B) {
|
||||
benchEach(b, 10, NewThreadUnsafeSetGeneric[int]())
|
||||
benchEach(b, 10, NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkEach100Safe(b *testing.B) {
|
||||
benchEach(b, 100, NewSetGeneric[int]())
|
||||
benchEach(b, 100, NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkEach100Unsafe(b *testing.B) {
|
||||
benchEach(b, 100, NewThreadUnsafeSetGeneric[int]())
|
||||
benchEach(b, 100, NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func benchIter(b *testing.B, n int, s SetGeneric[int]) {
|
||||
func benchIter(b *testing.B, n int, s Set[int]) {
|
||||
nums := nrand(n)
|
||||
for _, v := range nums {
|
||||
s.Add(v)
|
||||
|
@ -580,30 +580,30 @@ func benchIter(b *testing.B, n int, s SetGeneric[int]) {
|
|||
}
|
||||
|
||||
func BenchmarkIter1Safe(b *testing.B) {
|
||||
benchIter(b, 1, NewSetGeneric[int]())
|
||||
benchIter(b, 1, NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIter1Unsafe(b *testing.B) {
|
||||
benchIter(b, 1, NewThreadUnsafeSetGeneric[int]())
|
||||
benchIter(b, 1, NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIter10Safe(b *testing.B) {
|
||||
benchIter(b, 10, NewSetGeneric[int]())
|
||||
benchIter(b, 10, NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIter10Unsafe(b *testing.B) {
|
||||
benchIter(b, 10, NewThreadUnsafeSetGeneric[int]())
|
||||
benchIter(b, 10, NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIter100Safe(b *testing.B) {
|
||||
benchIter(b, 100, NewSetGeneric[int]())
|
||||
benchIter(b, 100, NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIter100Unsafe(b *testing.B) {
|
||||
benchIter(b, 100, NewThreadUnsafeSetGeneric[int]())
|
||||
benchIter(b, 100, NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func benchIterator(b *testing.B, n int, s SetGeneric[int]) {
|
||||
func benchIterator(b *testing.B, n int, s Set[int]) {
|
||||
nums := nrand(n)
|
||||
for _, v := range nums {
|
||||
s.Add(v)
|
||||
|
@ -619,30 +619,30 @@ func benchIterator(b *testing.B, n int, s SetGeneric[int]) {
|
|||
}
|
||||
|
||||
func BenchmarkIterator1Safe(b *testing.B) {
|
||||
benchIterator(b, 1, NewSetGeneric[int]())
|
||||
benchIterator(b, 1, NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIterator1Unsafe(b *testing.B) {
|
||||
benchIterator(b, 1, NewThreadUnsafeSetGeneric[int]())
|
||||
benchIterator(b, 1, NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIterator10Safe(b *testing.B) {
|
||||
benchIterator(b, 10, NewSetGeneric[int]())
|
||||
benchIterator(b, 10, NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIterator10Unsafe(b *testing.B) {
|
||||
benchIterator(b, 10, NewThreadUnsafeSetGeneric[int]())
|
||||
benchIterator(b, 10, NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIterator100Safe(b *testing.B) {
|
||||
benchIterator(b, 100, NewSetGeneric[int]())
|
||||
benchIterator(b, 100, NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkIterator100Unsafe(b *testing.B) {
|
||||
benchIterator(b, 100, NewThreadUnsafeSetGeneric[int]())
|
||||
benchIterator(b, 100, NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func benchString(b *testing.B, n int, s SetGeneric[int]) {
|
||||
func benchString(b *testing.B, n int, s Set[int]) {
|
||||
nums := nrand(n)
|
||||
for _, v := range nums {
|
||||
s.Add(v)
|
||||
|
@ -655,30 +655,30 @@ func benchString(b *testing.B, n int, s SetGeneric[int]) {
|
|||
}
|
||||
|
||||
func BenchmarkString1Safe(b *testing.B) {
|
||||
benchString(b, 1, NewSetGeneric[int]())
|
||||
benchString(b, 1, NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkString1Unsafe(b *testing.B) {
|
||||
benchString(b, 1, NewThreadUnsafeSetGeneric[int]())
|
||||
benchString(b, 1, NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkString10Safe(b *testing.B) {
|
||||
benchString(b, 10, NewSetGeneric[int]())
|
||||
benchString(b, 10, NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkString10Unsafe(b *testing.B) {
|
||||
benchString(b, 10, NewThreadUnsafeSetGeneric[int]())
|
||||
benchString(b, 10, NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkString100Safe(b *testing.B) {
|
||||
benchString(b, 100, NewSetGeneric[int]())
|
||||
benchString(b, 100, NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkString100Unsafe(b *testing.B) {
|
||||
benchString(b, 100, NewThreadUnsafeSetGeneric[int]())
|
||||
benchString(b, 100, NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
||||
func benchToSlice(b *testing.B, s SetGeneric[int]) {
|
||||
func benchToSlice(b *testing.B, s Set[int]) {
|
||||
nums := nrand(b.N)
|
||||
for _, v := range nums {
|
||||
s.Add(v)
|
||||
|
@ -691,9 +691,9 @@ func benchToSlice(b *testing.B, s SetGeneric[int]) {
|
|||
}
|
||||
|
||||
func BenchmarkToSliceSafe(b *testing.B) {
|
||||
benchToSlice(b, NewSetGeneric[int]())
|
||||
benchToSlice(b, NewSet[int]())
|
||||
}
|
||||
|
||||
func BenchmarkToSliceUnsafe(b *testing.B) {
|
||||
benchToSlice(b, NewThreadUnsafeSetGeneric[int]())
|
||||
benchToSlice(b, NewThreadUnsafeSet[int]())
|
||||
}
|
||||
|
|
12
iterator.go
12
iterator.go
|
@ -27,13 +27,13 @@ package mapset
|
|||
|
||||
// Iterator defines an iterator over a Set, its C channel can be used to range over the Set's
|
||||
// elements.
|
||||
type Iterator struct {
|
||||
C <-chan interface{}
|
||||
type Iterator[T comparable] struct {
|
||||
C <-chan T
|
||||
stop chan struct{}
|
||||
}
|
||||
|
||||
// Stop stops the Iterator, no further elements will be received on C, C will be closed.
|
||||
func (i *Iterator) Stop() {
|
||||
func (i *Iterator[T]) Stop() {
|
||||
// Allows for Stop() to be called multiple times
|
||||
// (close() panics when called on already closed channel)
|
||||
defer func() {
|
||||
|
@ -48,10 +48,10 @@ func (i *Iterator) Stop() {
|
|||
}
|
||||
|
||||
// newIterator returns a new Iterator instance together with its item and stop channels.
|
||||
func newIterator() (*Iterator, chan<- interface{}, <-chan struct{}) {
|
||||
itemChan := make(chan interface{})
|
||||
func newIterator[T comparable]() (*Iterator[T], chan<- T, <-chan struct{}) {
|
||||
itemChan := make(chan T)
|
||||
stopChan := make(chan struct{})
|
||||
return &Iterator{
|
||||
return &Iterator[T]{
|
||||
C: itemChan,
|
||||
stop: stopChan,
|
||||
}, itemChan, stopChan
|
||||
|
|
|
@ -35,7 +35,7 @@ type yourType struct {
|
|||
|
||||
func Test_ExampleIterator(t *testing.T) {
|
||||
|
||||
s := NewSetFromSliceGeneric[*yourType]([]*yourType{
|
||||
s := NewSetFromSlice[*yourType]([]*yourType{
|
||||
&yourType{name: "Alise"},
|
||||
&yourType{name: "Bob"},
|
||||
&yourType{name: "John"},
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
Open Source Initiative OSI - The MIT License (MIT):Licensing
|
||||
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
package mapset
|
||||
|
||||
// IteratorGeneric defines an iterator over a Set, its C channel can be used to range over the Set's
|
||||
// elements.
|
||||
type IteratorGeneric[T comparable] struct {
|
||||
C <-chan T
|
||||
stop chan struct{}
|
||||
}
|
||||
|
||||
// Stop stops the Iterator, no further elements will be received on C, C will be closed.
|
||||
func (i *IteratorGeneric[T]) Stop() {
|
||||
// Allows for Stop() to be called multiple times
|
||||
// (close() panics when called on already closed channel)
|
||||
defer func() {
|
||||
recover()
|
||||
}()
|
||||
|
||||
close(i.stop)
|
||||
|
||||
// Exhaust any remaining elements.
|
||||
for range i.C {
|
||||
}
|
||||
}
|
||||
|
||||
// newIterator returns a new Iterator instance together with its item and stop channels.
|
||||
func newIteratorGeneric[T comparable]() (*IteratorGeneric[T], chan<- T, <-chan struct{}) {
|
||||
itemChan := make(chan T)
|
||||
stopChan := make(chan struct{})
|
||||
return &IteratorGeneric[T]{
|
||||
C: itemChan,
|
||||
stop: stopChan,
|
||||
}, itemChan, stopChan
|
||||
}
|
89
set.go
89
set.go
|
@ -23,7 +23,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|||
SOFTWARE.
|
||||
*/
|
||||
|
||||
// Package mapset implements a simple and generic set collection.
|
||||
// Package mapset implements a simple and set collection.
|
||||
// Items stored within it are unordered and unique. It supports
|
||||
// typical set operations: membership testing, intersection, union,
|
||||
// difference, symmetric difference and cloning.
|
||||
|
@ -38,10 +38,10 @@ package mapset
|
|||
// Set is the primary interface provided by the mapset package. It
|
||||
// represents an unordered set of data and a large number of
|
||||
// operations that can be applied to that set.
|
||||
type Set interface {
|
||||
type Set[T comparable] interface {
|
||||
// Adds an element to the set. Returns whether
|
||||
// the item was added.
|
||||
Add(i interface{}) bool
|
||||
Add(val T) bool
|
||||
|
||||
// Returns the number of elements in the set.
|
||||
Cardinality() int
|
||||
|
@ -52,11 +52,11 @@ type Set interface {
|
|||
|
||||
// Returns a clone of the set using the same
|
||||
// implementation, duplicating all keys.
|
||||
Clone() Set
|
||||
Clone() Set[T]
|
||||
|
||||
// Returns whether the given items
|
||||
// are all in the set.
|
||||
Contains(i ...interface{}) bool
|
||||
Contains(val ...T) bool
|
||||
|
||||
// Returns the difference between this set
|
||||
// and other. The returned set will contain
|
||||
|
@ -67,7 +67,7 @@ type Set interface {
|
|||
// must be of the same type as the receiver
|
||||
// of the method. Otherwise, Difference will
|
||||
// panic.
|
||||
Difference(other Set) Set
|
||||
Difference(other Set[T]) Set[T]
|
||||
|
||||
// Determines if two sets are equal to each
|
||||
// other. If they have the same cardinality
|
||||
|
@ -78,7 +78,7 @@ type Set interface {
|
|||
// Note that the argument to Equal must be
|
||||
// of the same type as the receiver of the
|
||||
// method. Otherwise, Equal will panic.
|
||||
Equal(other Set) bool
|
||||
Equal(other Set[T]) bool
|
||||
|
||||
// Returns a new set containing only the elements
|
||||
// that exist only in both sets.
|
||||
|
@ -87,7 +87,7 @@ type Set interface {
|
|||
// must be of the same type as the receiver
|
||||
// of the method. Otherwise, Intersect will
|
||||
// panic.
|
||||
Intersect(other Set) Set
|
||||
Intersect(other Set[T]) Set[T]
|
||||
|
||||
// Determines if every element in this set is in
|
||||
// the other set but the two sets are not equal.
|
||||
|
@ -96,7 +96,7 @@ type Set interface {
|
|||
// must be of the same type as the receiver
|
||||
// of the method. Otherwise, IsProperSubset
|
||||
// will panic.
|
||||
IsProperSubset(other Set) bool
|
||||
IsProperSubset(other Set[T]) bool
|
||||
|
||||
// Determines if every element in the other set
|
||||
// is in this set but the two sets are not
|
||||
|
@ -106,7 +106,7 @@ type Set interface {
|
|||
// must be of the same type as the receiver
|
||||
// of the method. Otherwise, IsSuperset will
|
||||
// panic.
|
||||
IsProperSuperset(other Set) bool
|
||||
IsProperSuperset(other Set[T]) bool
|
||||
|
||||
// Determines if every element in this set is in
|
||||
// the other set.
|
||||
|
@ -115,7 +115,7 @@ type Set interface {
|
|||
// must be of the same type as the receiver
|
||||
// of the method. Otherwise, IsSubset will
|
||||
// panic.
|
||||
IsSubset(other Set) bool
|
||||
IsSubset(other Set[T]) bool
|
||||
|
||||
// Determines if every element in the other set
|
||||
// is in this set.
|
||||
|
@ -124,22 +124,22 @@ type Set interface {
|
|||
// must be of the same type as the receiver
|
||||
// of the method. Otherwise, IsSuperset will
|
||||
// panic.
|
||||
IsSuperset(other Set) bool
|
||||
IsSuperset(other Set[T]) bool
|
||||
|
||||
// Iterates over elements and executes the passed func against each element.
|
||||
// If passed func returns true, stop iteration at the time.
|
||||
Each(func(interface{}) bool)
|
||||
Each(func(T) bool)
|
||||
|
||||
// Returns a channel of elements that you can
|
||||
// range over.
|
||||
Iter() <-chan interface{}
|
||||
Iter() <-chan T
|
||||
|
||||
// Returns an Iterator object that you can
|
||||
// use to range over the set.
|
||||
Iterator() *Iterator
|
||||
Iterator() *Iterator[T]
|
||||
|
||||
// Remove a single element from the set.
|
||||
Remove(i interface{})
|
||||
Remove(i T)
|
||||
|
||||
// Provides a convenient string representation
|
||||
// of the current state of the set.
|
||||
|
@ -152,66 +152,73 @@ type Set interface {
|
|||
// must be of the same type as the receiver
|
||||
// of the method. Otherwise, SymmetricDifference
|
||||
// will panic.
|
||||
SymmetricDifference(other Set) Set
|
||||
SymmetricDifference(other Set[T]) Set[T]
|
||||
|
||||
// Returns a new set with all elements in both sets.
|
||||
//
|
||||
// Note that the argument to Union must be of the
|
||||
|
||||
// same type as the receiver of the method.
|
||||
// Otherwise, IsSuperset will panic.
|
||||
Union(other Set) Set
|
||||
Union(other Set[T]) Set[T]
|
||||
|
||||
// Pop removes and returns an arbitrary item from the set.
|
||||
Pop() interface{}
|
||||
Pop() any
|
||||
|
||||
// Returns all subsets of a given set (Power Set).
|
||||
PowerSet() Set
|
||||
// PowerSet({x, y, z}) -> {{}, {x}, {y}, {z}, {x, y}, {x, z}, {y, z}, {x, y, z}}
|
||||
PowerSet() Set[any]
|
||||
|
||||
// Returns the Cartesian Product of two sets.
|
||||
CartesianProduct(other Set) Set
|
||||
CartesianProduct(other Set[T]) Set[any]
|
||||
|
||||
// Returns the members of the set as a slice.
|
||||
ToSlice() []interface{}
|
||||
ToSlice() []T
|
||||
|
||||
// MarshalJSON will marshal the set into a JSON-based representation.
|
||||
MarshalJSON() ([]byte, error)
|
||||
|
||||
// UnmarshalJSON will unmarshal a JSON-based byte slice into a full Set datastructure.
|
||||
// For this to work, set subtypes must implemented the Marshal/Unmarshal interface.
|
||||
UnmarshalJSON(b []byte) error
|
||||
}
|
||||
|
||||
// NewSet creates and returns a reference to an empty set. Operations
|
||||
// on the resulting set are thread-safe.
|
||||
func NewSet(s ...interface{}) Set {
|
||||
set := newThreadSafeSet()
|
||||
for _, item := range s {
|
||||
set.Add(item)
|
||||
func NewSet[T comparable](vals ...T) Set[T] {
|
||||
s := newThreadSafeSet[T]()
|
||||
for _, item := range vals {
|
||||
s.Add(item)
|
||||
}
|
||||
return &set
|
||||
return &s
|
||||
}
|
||||
|
||||
// NewSetWith creates and returns a new set with the given elements.
|
||||
// Operations on the resulting set are thread-safe.
|
||||
func NewSetWith(elts ...interface{}) Set {
|
||||
return NewSetFromSlice(elts)
|
||||
func NewSetWith[T comparable](vals ...T) Set[T] {
|
||||
return NewSetFromSlice[T](vals)
|
||||
}
|
||||
|
||||
// NewSetFromSlice creates and returns a reference to a set from an
|
||||
// existing slice. Operations on the resulting set are thread-safe.
|
||||
func NewSetFromSlice(s []interface{}) Set {
|
||||
a := NewSet(s...)
|
||||
return a
|
||||
func NewSetFromSlice[T comparable](v []T) Set[T] {
|
||||
s := NewSet(v...)
|
||||
return s
|
||||
}
|
||||
|
||||
// NewThreadUnsafeSet creates and returns a reference to an empty set.
|
||||
// Operations on the resulting set are not thread-safe.
|
||||
func NewThreadUnsafeSet() Set {
|
||||
set := newThreadUnsafeSet()
|
||||
return &set
|
||||
func NewThreadUnsafeSet[T comparable]() Set[T] {
|
||||
s := newThreadUnsafeSet[T]()
|
||||
return &s
|
||||
}
|
||||
|
||||
// NewThreadUnsafeSetFromSlice creates and returns a reference to a
|
||||
// set from an existing slice. Operations on the resulting set are
|
||||
// not thread-safe.
|
||||
func NewThreadUnsafeSetFromSlice(s []interface{}) Set {
|
||||
a := NewThreadUnsafeSet()
|
||||
for _, item := range s {
|
||||
a.Add(item)
|
||||
func NewThreadUnsafeSetFromSlice[T comparable](v []T) Set[T] {
|
||||
s := NewThreadUnsafeSet[T]()
|
||||
for _, item := range v {
|
||||
s.Add(item)
|
||||
}
|
||||
return a
|
||||
return s
|
||||
}
|
||||
|
|
229
set_generic.go
229
set_generic.go
|
@ -1,229 +0,0 @@
|
|||
/*
|
||||
Open Source Initiative OSI - The MIT License (MIT):Licensing
|
||||
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
// Package mapset implements a simple and generic set collection.
|
||||
// Items stored within it are unordered and unique. It supports
|
||||
// typical set operations: membership testing, intersection, union,
|
||||
// difference, symmetric difference and cloning.
|
||||
//
|
||||
// Package mapset provides two implementations of the Set
|
||||
// interface. The default implementation is safe for concurrent
|
||||
// access, but a non-thread-safe implementation is also provided for
|
||||
// programs that can benefit from the slight speed improvement and
|
||||
// that can enforce mutual exclusion through other means.
|
||||
package mapset
|
||||
|
||||
// TODO: delete this...just messing with generics.
|
||||
// func Equal[T comparable](a, b T) bool {
|
||||
// return a == b
|
||||
// }
|
||||
|
||||
// Set is the primary interface provided by the mapset package. It
|
||||
// represents an unordered set of data and a large number of
|
||||
// operations that can be applied to that set.
|
||||
type SetGeneric[T comparable] interface {
|
||||
// Adds an element to the set. Returns whether
|
||||
// the item was added.
|
||||
Add(val T) bool
|
||||
|
||||
// Returns the number of elements in the set.
|
||||
Cardinality() int
|
||||
|
||||
// Removes all elements from the set, leaving
|
||||
// the empty set.
|
||||
Clear()
|
||||
|
||||
// Returns a clone of the set using the same
|
||||
// implementation, duplicating all keys.
|
||||
Clone() SetGeneric[T]
|
||||
|
||||
// Returns whether the given items
|
||||
// are all in the set.
|
||||
Contains(val ...T) bool
|
||||
|
||||
// Returns the difference between this set
|
||||
// and other. The returned set will contain
|
||||
// all elements of this set that are not also
|
||||
// elements of other.
|
||||
//
|
||||
// Note that the argument to Difference
|
||||
// must be of the same type as the receiver
|
||||
// of the method. Otherwise, Difference will
|
||||
// panic.
|
||||
Difference(other SetGeneric[T]) SetGeneric[T]
|
||||
|
||||
// Determines if two sets are equal to each
|
||||
// other. If they have the same cardinality
|
||||
// and contain the same elements, they are
|
||||
// considered equal. The order in which
|
||||
// the elements were added is irrelevant.
|
||||
//
|
||||
// Note that the argument to Equal must be
|
||||
// of the same type as the receiver of the
|
||||
// method. Otherwise, Equal will panic.
|
||||
Equal(other SetGeneric[T]) bool
|
||||
|
||||
// Returns a new set containing only the elements
|
||||
// that exist only in both sets.
|
||||
//
|
||||
// Note that the argument to Intersect
|
||||
// must be of the same type as the receiver
|
||||
// of the method. Otherwise, Intersect will
|
||||
// panic.
|
||||
Intersect(other SetGeneric[T]) SetGeneric[T]
|
||||
|
||||
// Determines if every element in this set is in
|
||||
// the other set but the two sets are not equal.
|
||||
//
|
||||
// Note that the argument to IsProperSubset
|
||||
// must be of the same type as the receiver
|
||||
// of the method. Otherwise, IsProperSubset
|
||||
// will panic.
|
||||
IsProperSubset(other SetGeneric[T]) bool
|
||||
|
||||
// Determines if every element in the other set
|
||||
// is in this set but the two sets are not
|
||||
// equal.
|
||||
//
|
||||
// Note that the argument to IsSuperset
|
||||
// must be of the same type as the receiver
|
||||
// of the method. Otherwise, IsSuperset will
|
||||
// panic.
|
||||
IsProperSuperset(other SetGeneric[T]) bool
|
||||
|
||||
// Determines if every element in this set is in
|
||||
// the other set.
|
||||
//
|
||||
// Note that the argument to IsSubset
|
||||
// must be of the same type as the receiver
|
||||
// of the method. Otherwise, IsSubset will
|
||||
// panic.
|
||||
IsSubset(other SetGeneric[T]) bool
|
||||
|
||||
// Determines if every element in the other set
|
||||
// is in this set.
|
||||
//
|
||||
// Note that the argument to IsSuperset
|
||||
// must be of the same type as the receiver
|
||||
// of the method. Otherwise, IsSuperset will
|
||||
// panic.
|
||||
IsSuperset(other SetGeneric[T]) bool
|
||||
|
||||
// Iterates over elements and executes the passed func against each element.
|
||||
// If passed func returns true, stop iteration at the time.
|
||||
Each(func(T) bool)
|
||||
|
||||
// Returns a channel of elements that you can
|
||||
// range over.
|
||||
Iter() <-chan T
|
||||
|
||||
// Returns an Iterator object that you can
|
||||
// use to range over the set.
|
||||
Iterator() *IteratorGeneric[T]
|
||||
|
||||
// Remove a single element from the set.
|
||||
Remove(i T)
|
||||
|
||||
// Provides a convenient string representation
|
||||
// of the current state of the set.
|
||||
String() string
|
||||
|
||||
// Returns a new set with all elements which are
|
||||
// in either this set or the other set but not in both.
|
||||
//
|
||||
// Note that the argument to SymmetricDifference
|
||||
// must be of the same type as the receiver
|
||||
// of the method. Otherwise, SymmetricDifference
|
||||
// will panic.
|
||||
SymmetricDifference(other SetGeneric[T]) SetGeneric[T]
|
||||
|
||||
// Returns a new set with all elements in both sets.
|
||||
//
|
||||
// Note that the argument to Union must be of the
|
||||
// same type as the receiver of the method.
|
||||
// Otherwise, IsSuperset will panic.
|
||||
Union(other SetGeneric[T]) SetGeneric[T]
|
||||
|
||||
// Pop removes and returns an arbitrary item from the set.
|
||||
Pop() any
|
||||
|
||||
// Returns all subsets of a given set (Power Set).
|
||||
// PowerSet({x, y, z}) -> {{}, {x}, {y}, {z}, {x, y}, {x, z}, {y, z}, {x, y, z}}
|
||||
PowerSet() SetGeneric[any]
|
||||
|
||||
// Returns the Cartesian Product of two sets.
|
||||
CartesianProduct(other SetGeneric[T]) SetGeneric[any]
|
||||
|
||||
// Returns the members of the set as a slice.
|
||||
ToSlice() []T
|
||||
|
||||
// MarshalJSON will marshal the set into a JSON-based representation.
|
||||
MarshalJSON() ([]byte, error)
|
||||
|
||||
// UnmarshalJSON will unmarshal a JSON-based byte slice into a full Set datastructure.
|
||||
// For this to work, set subtypes must implemented the Marshal/Unmarshal interface.
|
||||
UnmarshalJSON(b []byte) error
|
||||
}
|
||||
|
||||
// NewSet creates and returns a reference to an empty set. Operations
|
||||
// on the resulting set are thread-safe.
|
||||
func NewSetGeneric[T comparable](vals ...T) SetGeneric[T] {
|
||||
s := newThreadSafeSetGeneric[T]()
|
||||
for _, item := range vals {
|
||||
s.Add(item)
|
||||
}
|
||||
return &s
|
||||
}
|
||||
|
||||
// NewSetWith creates and returns a new set with the given elements.
|
||||
// Operations on the resulting set are thread-safe.
|
||||
func NewSetWithGeneric[T comparable](vals ...T) SetGeneric[T] {
|
||||
return NewSetFromSliceGeneric[T](vals)
|
||||
}
|
||||
|
||||
// NewSetFromSlice creates and returns a reference to a set from an
|
||||
// existing slice. Operations on the resulting set are thread-safe.
|
||||
func NewSetFromSliceGeneric[T comparable](v []T) SetGeneric[T] {
|
||||
s := NewSetGeneric(v...)
|
||||
return s
|
||||
}
|
||||
|
||||
// NewThreadUnsafeSetGeneric creates and returns a reference to an empty set.
|
||||
// Operations on the resulting set are not thread-safe.
|
||||
func NewThreadUnsafeSetGeneric[T comparable]() SetGeneric[T] {
|
||||
s := newThreadUnsafeSetGeneric[T]()
|
||||
return &s
|
||||
}
|
||||
|
||||
// NewThreadUnsafeSetFromSlice creates and returns a reference to a
|
||||
// set from an existing slice. Operations on the resulting set are
|
||||
// not thread-safe.
|
||||
func NewThreadUnsafeSetFromSliceGeneric[T comparable](v []T) SetGeneric[T] {
|
||||
s := NewThreadUnsafeSetGeneric[T]()
|
||||
for _, item := range v {
|
||||
s.Add(item)
|
||||
}
|
||||
return s
|
||||
}
|
172
set_test.go
172
set_test.go
|
@ -27,65 +27,43 @@ package mapset
|
|||
|
||||
import "testing"
|
||||
|
||||
func makeSet(ints []int) Set {
|
||||
set := NewSet()
|
||||
for _, i := range ints {
|
||||
set.Add(i)
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
func makeSetInt(ints []int) SetGeneric[int] {
|
||||
s := NewSetGeneric[int]()
|
||||
func makeSetInt(ints []int) Set[int] {
|
||||
s := NewSet[int]()
|
||||
for _, i := range ints {
|
||||
s.Add(i)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func makeUnsafeSet(ints []int) Set {
|
||||
set := NewThreadUnsafeSet()
|
||||
for _, i := range ints {
|
||||
set.Add(i)
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
func makeUnsafeSetInt(ints []int) SetGeneric[int] {
|
||||
s := NewThreadUnsafeSetGeneric[int]()
|
||||
func makeUnsafeSetInt(ints []int) Set[int] {
|
||||
s := NewThreadUnsafeSet[int]()
|
||||
for _, i := range ints {
|
||||
s.Add(i)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func assertEqual(a, b Set, t *testing.T) {
|
||||
if !a.Equal(b) {
|
||||
t.Errorf("%v != %v\n", a, b)
|
||||
}
|
||||
}
|
||||
|
||||
func assertEqualGeneric[T comparable](a, b SetGeneric[T], t *testing.T) {
|
||||
func assertEqual[T comparable](a, b Set[T], t *testing.T) {
|
||||
if !a.Equal(b) {
|
||||
t.Errorf("%v != %v\n", a, b)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_NewSet(t *testing.T) {
|
||||
a := NewSetGeneric[int]()
|
||||
a := NewSet[int]()
|
||||
if a.Cardinality() != 0 {
|
||||
t.Error("NewSet should start out as an empty set")
|
||||
}
|
||||
|
||||
assertEqualGeneric(NewSetFromSliceGeneric[int]([]int{}), NewSetGeneric[int](), t)
|
||||
assertEqualGeneric(NewSetFromSliceGeneric[int]([]int{1}), NewSetGeneric[int](1), t)
|
||||
assertEqualGeneric(NewSetFromSliceGeneric[int]([]int{1, 2}), NewSetGeneric[int](1, 2), t)
|
||||
assertEqualGeneric(NewSetFromSliceGeneric[string]([]string{"a"}), NewSetGeneric[string]("a"), t)
|
||||
assertEqualGeneric(NewSetFromSliceGeneric[string]([]string{"a", "b"}), NewSetGeneric[string]("a", "b"), t)
|
||||
assertEqual(NewSetFromSlice[int]([]int{}), NewSet[int](), t)
|
||||
assertEqual(NewSetFromSlice[int]([]int{1}), NewSet[int](1), t)
|
||||
assertEqual(NewSetFromSlice[int]([]int{1, 2}), NewSet[int](1, 2), t)
|
||||
assertEqual(NewSetFromSlice[string]([]string{"a"}), NewSet[string]("a"), t)
|
||||
assertEqual(NewSetFromSlice[string]([]string{"a", "b"}), NewSet[string]("a", "b"), t)
|
||||
}
|
||||
|
||||
func Test_NewUnsafeSet(t *testing.T) {
|
||||
a := NewThreadUnsafeSetGeneric[int]()
|
||||
a := NewThreadUnsafeSet[int]()
|
||||
|
||||
if a.Cardinality() != 0 {
|
||||
t.Error("NewSet should start out as an empty set")
|
||||
|
@ -175,7 +153,7 @@ func Test_RemoveUnsafeSet(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_ContainsSet(t *testing.T) {
|
||||
a := NewSetGeneric[int]()
|
||||
a := NewSet[int]()
|
||||
|
||||
a.Add(71)
|
||||
|
||||
|
@ -199,7 +177,7 @@ func Test_ContainsSet(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_ContainsUnsafeSet(t *testing.T) {
|
||||
a := NewThreadUnsafeSetGeneric[int]()
|
||||
a := NewThreadUnsafeSet[int]()
|
||||
|
||||
a.Add(71)
|
||||
|
||||
|
@ -267,7 +245,7 @@ func Test_ClearUnsafeSet(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_CardinalitySet(t *testing.T) {
|
||||
a := NewSetGeneric[int]()
|
||||
a := NewSet[int]()
|
||||
|
||||
if a.Cardinality() != 0 {
|
||||
t.Error("set should be an empty set")
|
||||
|
@ -299,7 +277,7 @@ func Test_CardinalitySet(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_CardinalityUnsafeSet(t *testing.T) {
|
||||
a := NewThreadUnsafeSetGeneric[int]()
|
||||
a := NewThreadUnsafeSet[int]()
|
||||
|
||||
if a.Cardinality() != 0 {
|
||||
t.Error("set should be an empty set")
|
||||
|
@ -333,7 +311,7 @@ func Test_CardinalityUnsafeSet(t *testing.T) {
|
|||
func Test_SetIsSubset(t *testing.T) {
|
||||
a := makeSetInt([]int{1, 2, 3, 5, 7})
|
||||
|
||||
b := NewSetGeneric[int]()
|
||||
b := NewSet[int]()
|
||||
b.Add(3)
|
||||
b.Add(5)
|
||||
b.Add(7)
|
||||
|
@ -373,7 +351,7 @@ func Test_SetIsProperSubset(t *testing.T) {
|
|||
func Test_UnsafeSetIsSubset(t *testing.T) {
|
||||
a := makeUnsafeSetInt([]int{1, 2, 3, 5, 7})
|
||||
|
||||
b := NewThreadUnsafeSetGeneric[int]()
|
||||
b := NewThreadUnsafeSet[int]()
|
||||
b.Add(3)
|
||||
b.Add(5)
|
||||
b.Add(7)
|
||||
|
@ -391,7 +369,7 @@ func Test_UnsafeSetIsSubset(t *testing.T) {
|
|||
|
||||
func Test_UnsafeSetIsProperSubset(t *testing.T) {
|
||||
a := makeUnsafeSetInt([]int{1, 2, 3, 5, 7})
|
||||
b := NewThreadUnsafeSetGeneric[int]()
|
||||
b := NewThreadUnsafeSet[int]()
|
||||
b.Add(7)
|
||||
b.Add(1)
|
||||
b.Add(5)
|
||||
|
@ -416,14 +394,14 @@ func Test_UnsafeSetIsProperSubset(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_SetIsSuperset(t *testing.T) {
|
||||
a := NewSetGeneric[int]()
|
||||
a := NewSet[int]()
|
||||
a.Add(9)
|
||||
a.Add(5)
|
||||
a.Add(2)
|
||||
a.Add(1)
|
||||
a.Add(11)
|
||||
|
||||
b := NewSetGeneric[int]()
|
||||
b := NewSet[int]()
|
||||
b.Add(5)
|
||||
b.Add(2)
|
||||
b.Add(11)
|
||||
|
@ -440,12 +418,12 @@ func Test_SetIsSuperset(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_SetIsProperSuperset(t *testing.T) {
|
||||
a := NewSetGeneric[int]()
|
||||
a := NewSet[int]()
|
||||
a.Add(5)
|
||||
a.Add(2)
|
||||
a.Add(11)
|
||||
|
||||
b := NewSetGeneric[int]()
|
||||
b := NewSet[int]()
|
||||
b.Add(2)
|
||||
b.Add(5)
|
||||
b.Add(11)
|
||||
|
@ -477,14 +455,14 @@ func Test_SetIsProperSuperset(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_UnsafeSetIsSuperset(t *testing.T) {
|
||||
a := NewThreadUnsafeSetGeneric[int]()
|
||||
a := NewThreadUnsafeSet[int]()
|
||||
a.Add(9)
|
||||
a.Add(5)
|
||||
a.Add(2)
|
||||
a.Add(1)
|
||||
a.Add(11)
|
||||
|
||||
b := NewThreadUnsafeSetGeneric[int]()
|
||||
b := NewThreadUnsafeSet[int]()
|
||||
b.Add(5)
|
||||
b.Add(2)
|
||||
b.Add(11)
|
||||
|
@ -501,12 +479,12 @@ func Test_UnsafeSetIsSuperset(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_UnsafeSetIsProperSuperset(t *testing.T) {
|
||||
a := NewThreadUnsafeSetGeneric[int]()
|
||||
a := NewThreadUnsafeSet[int]()
|
||||
a.Add(5)
|
||||
a.Add(2)
|
||||
a.Add(11)
|
||||
|
||||
b := NewThreadUnsafeSetGeneric[int]()
|
||||
b := NewThreadUnsafeSet[int]()
|
||||
b.Add(2)
|
||||
b.Add(5)
|
||||
b.Add(11)
|
||||
|
@ -538,9 +516,9 @@ func Test_UnsafeSetIsProperSuperset(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_SetUnion(t *testing.T) {
|
||||
a := NewSetGeneric[int]()
|
||||
a := NewSet[int]()
|
||||
|
||||
b := NewSetGeneric[int]()
|
||||
b := NewSet[int]()
|
||||
b.Add(1)
|
||||
b.Add(2)
|
||||
b.Add(3)
|
||||
|
@ -553,7 +531,7 @@ func Test_SetUnion(t *testing.T) {
|
|||
t.Error("set c is unioned with an empty set and therefore should have 5 elements in it")
|
||||
}
|
||||
|
||||
d := NewSetGeneric[int]()
|
||||
d := NewSet[int]()
|
||||
d.Add(10)
|
||||
d.Add(14)
|
||||
d.Add(0)
|
||||
|
@ -563,7 +541,7 @@ func Test_SetUnion(t *testing.T) {
|
|||
t.Error("set e should should have 8 elements in it after being unioned with set c to d")
|
||||
}
|
||||
|
||||
f := NewSetGeneric[int]()
|
||||
f := NewSet[int]()
|
||||
f.Add(14)
|
||||
f.Add(3)
|
||||
|
||||
|
@ -574,9 +552,9 @@ func Test_SetUnion(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_UnsafeSetUnion(t *testing.T) {
|
||||
a := NewThreadUnsafeSetGeneric[int]()
|
||||
a := NewThreadUnsafeSet[int]()
|
||||
|
||||
b := NewThreadUnsafeSetGeneric[int]()
|
||||
b := NewThreadUnsafeSet[int]()
|
||||
b.Add(1)
|
||||
b.Add(2)
|
||||
b.Add(3)
|
||||
|
@ -589,7 +567,7 @@ func Test_UnsafeSetUnion(t *testing.T) {
|
|||
t.Error("set c is unioned with an empty set and therefore should have 5 elements in it")
|
||||
}
|
||||
|
||||
d := NewThreadUnsafeSetGeneric[int]()
|
||||
d := NewThreadUnsafeSet[int]()
|
||||
d.Add(10)
|
||||
d.Add(14)
|
||||
d.Add(0)
|
||||
|
@ -599,7 +577,7 @@ func Test_UnsafeSetUnion(t *testing.T) {
|
|||
t.Error("set e should should have 8 elements in it after being unioned with set c to d")
|
||||
}
|
||||
|
||||
f := NewThreadUnsafeSetGeneric[int]()
|
||||
f := NewThreadUnsafeSet[int]()
|
||||
f.Add(14)
|
||||
f.Add(3)
|
||||
|
||||
|
@ -610,12 +588,12 @@ func Test_UnsafeSetUnion(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_SetIntersect(t *testing.T) {
|
||||
a := NewSetGeneric[int]()
|
||||
a := NewSet[int]()
|
||||
a.Add(1)
|
||||
a.Add(3)
|
||||
a.Add(5)
|
||||
|
||||
b := NewSetGeneric[int]()
|
||||
b := NewSet[int]()
|
||||
a.Add(2)
|
||||
a.Add(4)
|
||||
a.Add(6)
|
||||
|
@ -637,12 +615,12 @@ func Test_SetIntersect(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_UnsafeSetIntersect(t *testing.T) {
|
||||
a := NewThreadUnsafeSetGeneric[int]()
|
||||
a := NewThreadUnsafeSet[int]()
|
||||
a.Add(1)
|
||||
a.Add(3)
|
||||
a.Add(5)
|
||||
|
||||
b := NewThreadUnsafeSetGeneric[int]()
|
||||
b := NewThreadUnsafeSet[int]()
|
||||
a.Add(2)
|
||||
a.Add(4)
|
||||
a.Add(6)
|
||||
|
@ -664,12 +642,12 @@ func Test_UnsafeSetIntersect(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_SetDifference(t *testing.T) {
|
||||
a := NewSetGeneric[int]()
|
||||
a := NewSet[int]()
|
||||
a.Add(1)
|
||||
a.Add(2)
|
||||
a.Add(3)
|
||||
|
||||
b := NewSetGeneric[int]()
|
||||
b := NewSet[int]()
|
||||
b.Add(1)
|
||||
b.Add(3)
|
||||
b.Add(4)
|
||||
|
@ -685,12 +663,12 @@ func Test_SetDifference(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_UnsafeSetDifference(t *testing.T) {
|
||||
a := NewThreadUnsafeSetGeneric[int]()
|
||||
a := NewThreadUnsafeSet[int]()
|
||||
a.Add(1)
|
||||
a.Add(2)
|
||||
a.Add(3)
|
||||
|
||||
b := NewThreadUnsafeSetGeneric[int]()
|
||||
b := NewThreadUnsafeSet[int]()
|
||||
b.Add(1)
|
||||
b.Add(3)
|
||||
b.Add(4)
|
||||
|
@ -706,13 +684,13 @@ func Test_UnsafeSetDifference(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_SetSymmetricDifference(t *testing.T) {
|
||||
a := NewSetGeneric[int]()
|
||||
a := NewSet[int]()
|
||||
a.Add(1)
|
||||
a.Add(2)
|
||||
a.Add(3)
|
||||
a.Add(45)
|
||||
|
||||
b := NewSetGeneric[int]()
|
||||
b := NewSet[int]()
|
||||
b.Add(1)
|
||||
b.Add(3)
|
||||
b.Add(4)
|
||||
|
@ -728,13 +706,13 @@ func Test_SetSymmetricDifference(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_UnsafeSetSymmetricDifference(t *testing.T) {
|
||||
a := NewThreadUnsafeSetGeneric[int]()
|
||||
a := NewThreadUnsafeSet[int]()
|
||||
a.Add(1)
|
||||
a.Add(2)
|
||||
a.Add(3)
|
||||
a.Add(45)
|
||||
|
||||
b := NewThreadUnsafeSetGeneric[int]()
|
||||
b := NewThreadUnsafeSet[int]()
|
||||
b.Add(1)
|
||||
b.Add(3)
|
||||
b.Add(4)
|
||||
|
@ -750,8 +728,8 @@ func Test_UnsafeSetSymmetricDifference(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_SetEqual(t *testing.T) {
|
||||
a := NewSetGeneric[int]()
|
||||
b := NewSetGeneric[int]()
|
||||
a := NewSet[int]()
|
||||
b := NewSet[int]()
|
||||
|
||||
if !a.Equal(b) {
|
||||
t.Error("Both a and b are empty sets, and should be equal")
|
||||
|
@ -787,8 +765,8 @@ func Test_SetEqual(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_UnsafeSetEqual(t *testing.T) {
|
||||
a := NewThreadUnsafeSetGeneric[int]()
|
||||
b := NewThreadUnsafeSetGeneric[int]()
|
||||
a := NewThreadUnsafeSet[int]()
|
||||
b := NewThreadUnsafeSet[int]()
|
||||
|
||||
if !a.Equal(b) {
|
||||
t.Error("Both a and b are empty sets, and should be equal")
|
||||
|
@ -824,7 +802,7 @@ func Test_UnsafeSetEqual(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_SetClone(t *testing.T) {
|
||||
a := NewSetGeneric[int]()
|
||||
a := NewSet[int]()
|
||||
a.Add(1)
|
||||
a.Add(2)
|
||||
|
||||
|
@ -848,7 +826,7 @@ func Test_SetClone(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_UnsafeSetClone(t *testing.T) {
|
||||
a := NewThreadUnsafeSetGeneric[int]()
|
||||
a := NewThreadUnsafeSet[int]()
|
||||
a.Add(1)
|
||||
a.Add(2)
|
||||
|
||||
|
@ -872,14 +850,14 @@ func Test_UnsafeSetClone(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_Each(t *testing.T) {
|
||||
a := NewSetGeneric[string]()
|
||||
a := NewSet[string]()
|
||||
|
||||
a.Add("Z")
|
||||
a.Add("Y")
|
||||
a.Add("X")
|
||||
a.Add("W")
|
||||
|
||||
b := NewSetGeneric[string]()
|
||||
b := NewSet[string]()
|
||||
a.Each(func(elem string) bool {
|
||||
b.Add(elem)
|
||||
return false
|
||||
|
@ -903,14 +881,14 @@ func Test_Each(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_Iter(t *testing.T) {
|
||||
a := NewSetGeneric[string]()
|
||||
a := NewSet[string]()
|
||||
|
||||
a.Add("Z")
|
||||
a.Add("Y")
|
||||
a.Add("X")
|
||||
a.Add("W")
|
||||
|
||||
b := NewSetGeneric[string]()
|
||||
b := NewSet[string]()
|
||||
for val := range a.Iter() {
|
||||
b.Add(val)
|
||||
}
|
||||
|
@ -921,14 +899,14 @@ func Test_Iter(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_UnsafeIter(t *testing.T) {
|
||||
a := NewThreadUnsafeSet()
|
||||
a := NewThreadUnsafeSet[string]()
|
||||
|
||||
a.Add("Z")
|
||||
a.Add("Y")
|
||||
a.Add("X")
|
||||
a.Add("W")
|
||||
|
||||
b := NewThreadUnsafeSet()
|
||||
b := NewThreadUnsafeSet[string]()
|
||||
for val := range a.Iter() {
|
||||
b.Add(val)
|
||||
}
|
||||
|
@ -939,14 +917,14 @@ func Test_UnsafeIter(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_Iterator(t *testing.T) {
|
||||
a := NewSetGeneric[string]()
|
||||
a := NewSet[string]()
|
||||
|
||||
a.Add("Z")
|
||||
a.Add("Y")
|
||||
a.Add("X")
|
||||
a.Add("W")
|
||||
|
||||
b := NewSetGeneric[string]()
|
||||
b := NewSet[string]()
|
||||
for val := range a.Iterator().C {
|
||||
b.Add(val)
|
||||
}
|
||||
|
@ -957,14 +935,14 @@ func Test_Iterator(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_UnsafeIterator(t *testing.T) {
|
||||
a := NewThreadUnsafeSetGeneric[string]()
|
||||
a := NewThreadUnsafeSet[string]()
|
||||
|
||||
a.Add("Z")
|
||||
a.Add("Y")
|
||||
a.Add("X")
|
||||
a.Add("W")
|
||||
|
||||
b := NewThreadUnsafeSetGeneric[string]()
|
||||
b := NewThreadUnsafeSet[string]()
|
||||
for val := range a.Iterator().C {
|
||||
b.Add(val)
|
||||
}
|
||||
|
@ -975,7 +953,7 @@ func Test_UnsafeIterator(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_IteratorStop(t *testing.T) {
|
||||
a := NewSetGeneric[string]()
|
||||
a := NewSet[string]()
|
||||
|
||||
a.Add("Z")
|
||||
a.Add("Y")
|
||||
|
@ -990,14 +968,14 @@ func Test_IteratorStop(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_PopSafe(t *testing.T) {
|
||||
a := NewSetGeneric[string]()
|
||||
a := NewSet[string]()
|
||||
|
||||
a.Add("a")
|
||||
a.Add("b")
|
||||
a.Add("c")
|
||||
a.Add("d")
|
||||
|
||||
captureSet := NewSetGeneric[any]()
|
||||
captureSet := NewSet[any]()
|
||||
captureSet.Add(a.Pop())
|
||||
captureSet.Add(a.Pop())
|
||||
captureSet.Add(a.Pop())
|
||||
|
@ -1022,14 +1000,14 @@ func Test_PopSafe(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_PopUnsafe(t *testing.T) {
|
||||
a := NewThreadUnsafeSetGeneric[string]()
|
||||
a := NewThreadUnsafeSet[string]()
|
||||
|
||||
a.Add("a")
|
||||
a.Add("b")
|
||||
a.Add("c")
|
||||
a.Add("d")
|
||||
|
||||
captureSet := NewThreadUnsafeSetGeneric[any]()
|
||||
captureSet := NewThreadUnsafeSet[any]()
|
||||
captureSet.Add(a.Pop())
|
||||
captureSet.Add(a.Pop())
|
||||
captureSet.Add(a.Pop())
|
||||
|
@ -1054,7 +1032,7 @@ func Test_PopUnsafe(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_PowerSet(t *testing.T) {
|
||||
a := NewThreadUnsafeSetGeneric[string]()
|
||||
a := NewThreadUnsafeSet[string]()
|
||||
|
||||
a.Add("1")
|
||||
a.Add("delta")
|
||||
|
@ -1082,14 +1060,14 @@ func Test_PowerSetThreadSafe(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_EmptySetProperties(t *testing.T) {
|
||||
empty := NewSetGeneric[string]()
|
||||
empty := NewSet[string]()
|
||||
|
||||
a := NewSetGeneric[string]()
|
||||
a := NewSet[string]()
|
||||
a.Add("1")
|
||||
a.Add("foo")
|
||||
a.Add("bar")
|
||||
|
||||
b := NewSetGeneric[string]()
|
||||
b := NewSet[string]()
|
||||
b.Add("one")
|
||||
b.Add("two")
|
||||
b.Add("3")
|
||||
|
@ -1133,9 +1111,9 @@ func Test_EmptySetProperties(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_CartesianProduct(t *testing.T) {
|
||||
a := NewThreadUnsafeSetGeneric[any]()
|
||||
b := NewThreadUnsafeSetGeneric[any]()
|
||||
empty := NewThreadUnsafeSetGeneric[any]()
|
||||
a := NewThreadUnsafeSet[any]()
|
||||
b := NewThreadUnsafeSet[any]()
|
||||
empty := NewThreadUnsafeSet[any]()
|
||||
|
||||
a.Add(1)
|
||||
a.Add(2)
|
||||
|
|
244
threadsafe.go
244
threadsafe.go
|
@ -27,162 +27,165 @@ package mapset
|
|||
|
||||
import "sync"
|
||||
|
||||
type threadSafeSet struct {
|
||||
s threadUnsafeSet
|
||||
type threadSafeSet[T comparable] struct {
|
||||
sync.RWMutex
|
||||
uss threadUnsafeSet[T]
|
||||
}
|
||||
|
||||
func newThreadSafeSet() threadSafeSet {
|
||||
return threadSafeSet{s: newThreadUnsafeSet()}
|
||||
func newThreadSafeSet[T comparable]() threadSafeSet[T] {
|
||||
newUss := newThreadUnsafeSet[T]()
|
||||
return threadSafeSet[T]{
|
||||
uss: newUss,
|
||||
}
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) Add(i interface{}) bool {
|
||||
set.Lock()
|
||||
ret := set.s.Add(i)
|
||||
set.Unlock()
|
||||
func (s *threadSafeSet[T]) Add(v T) bool {
|
||||
s.Lock()
|
||||
ret := s.uss.Add(v)
|
||||
s.Unlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) Contains(i ...interface{}) bool {
|
||||
set.RLock()
|
||||
ret := set.s.Contains(i...)
|
||||
set.RUnlock()
|
||||
func (s *threadSafeSet[T]) Contains(v ...T) bool {
|
||||
s.RLock()
|
||||
ret := s.uss.Contains(v...)
|
||||
s.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) IsSubset(other Set) bool {
|
||||
o := other.(*threadSafeSet)
|
||||
func (s *threadSafeSet[T]) IsSubset(other Set[T]) bool {
|
||||
o := other.(*threadSafeSet[T])
|
||||
|
||||
set.RLock()
|
||||
s.RLock()
|
||||
o.RLock()
|
||||
|
||||
ret := set.s.IsSubset(&o.s)
|
||||
set.RUnlock()
|
||||
ret := s.uss.IsSubset(&o.uss)
|
||||
s.RUnlock()
|
||||
o.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) IsProperSubset(other Set) bool {
|
||||
o := other.(*threadSafeSet)
|
||||
func (s *threadSafeSet[T]) IsProperSubset(other Set[T]) bool {
|
||||
o := other.(*threadSafeSet[T])
|
||||
|
||||
set.RLock()
|
||||
defer set.RUnlock()
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
o.RLock()
|
||||
defer o.RUnlock()
|
||||
|
||||
return set.s.IsProperSubset(&o.s)
|
||||
return s.uss.IsProperSubset(&o.uss)
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) IsSuperset(other Set) bool {
|
||||
return other.IsSubset(set)
|
||||
func (s *threadSafeSet[T]) IsSuperset(other Set[T]) bool {
|
||||
return other.IsSubset(s)
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) IsProperSuperset(other Set) bool {
|
||||
return other.IsProperSubset(set)
|
||||
func (s *threadSafeSet[T]) IsProperSuperset(other Set[T]) bool {
|
||||
return other.IsProperSubset(s)
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) Union(other Set) Set {
|
||||
o := other.(*threadSafeSet)
|
||||
func (s *threadSafeSet[T]) Union(other Set[T]) Set[T] {
|
||||
o := other.(*threadSafeSet[T])
|
||||
|
||||
set.RLock()
|
||||
s.RLock()
|
||||
o.RLock()
|
||||
|
||||
unsafeUnion := set.s.Union(&o.s).(*threadUnsafeSet)
|
||||
ret := &threadSafeSet{s: *unsafeUnion}
|
||||
set.RUnlock()
|
||||
unsafeUnion := s.uss.Union(&o.uss).(*threadUnsafeSet[T])
|
||||
ret := &threadSafeSet[T]{uss: *unsafeUnion}
|
||||
s.RUnlock()
|
||||
o.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) Intersect(other Set) Set {
|
||||
o := other.(*threadSafeSet)
|
||||
func (s *threadSafeSet[T]) Intersect(other Set[T]) Set[T] {
|
||||
o := other.(*threadSafeSet[T])
|
||||
|
||||
set.RLock()
|
||||
s.RLock()
|
||||
o.RLock()
|
||||
|
||||
unsafeIntersection := set.s.Intersect(&o.s).(*threadUnsafeSet)
|
||||
ret := &threadSafeSet{s: *unsafeIntersection}
|
||||
set.RUnlock()
|
||||
unsafeIntersection := s.uss.Intersect(&o.uss).(*threadUnsafeSet[T])
|
||||
ret := &threadSafeSet[T]{uss: *unsafeIntersection}
|
||||
s.RUnlock()
|
||||
o.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) Difference(other Set) Set {
|
||||
o := other.(*threadSafeSet)
|
||||
func (s *threadSafeSet[T]) Difference(other Set[T]) Set[T] {
|
||||
o := other.(*threadSafeSet[T])
|
||||
|
||||
set.RLock()
|
||||
s.RLock()
|
||||
o.RLock()
|
||||
|
||||
unsafeDifference := set.s.Difference(&o.s).(*threadUnsafeSet)
|
||||
ret := &threadSafeSet{s: *unsafeDifference}
|
||||
set.RUnlock()
|
||||
unsafeDifference := s.uss.Difference(&o.uss).(*threadUnsafeSet[T])
|
||||
ret := &threadSafeSet[T]{uss: *unsafeDifference}
|
||||
s.RUnlock()
|
||||
o.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) SymmetricDifference(other Set) Set {
|
||||
o := other.(*threadSafeSet)
|
||||
func (s *threadSafeSet[T]) SymmetricDifference(other Set[T]) Set[T] {
|
||||
o := other.(*threadSafeSet[T])
|
||||
|
||||
set.RLock()
|
||||
s.RLock()
|
||||
o.RLock()
|
||||
|
||||
unsafeDifference := set.s.SymmetricDifference(&o.s).(*threadUnsafeSet)
|
||||
ret := &threadSafeSet{s: *unsafeDifference}
|
||||
set.RUnlock()
|
||||
unsafeDifference := s.uss.SymmetricDifference(&o.uss).(*threadUnsafeSet[T])
|
||||
ret := &threadSafeSet[T]{uss: *unsafeDifference}
|
||||
s.RUnlock()
|
||||
o.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) Clear() {
|
||||
set.Lock()
|
||||
set.s = newThreadUnsafeSet()
|
||||
set.Unlock()
|
||||
func (s *threadSafeSet[T]) Clear() {
|
||||
s.Lock()
|
||||
s.uss = newThreadUnsafeSet[T]()
|
||||
s.Unlock()
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) Remove(i interface{}) {
|
||||
set.Lock()
|
||||
delete(set.s, i)
|
||||
set.Unlock()
|
||||
func (s *threadSafeSet[T]) Remove(v T) {
|
||||
s.Lock()
|
||||
delete(s.uss, v)
|
||||
s.Unlock()
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) Cardinality() int {
|
||||
set.RLock()
|
||||
defer set.RUnlock()
|
||||
return len(set.s)
|
||||
func (s *threadSafeSet[T]) Cardinality() int {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
return len(s.uss)
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) Each(cb func(interface{}) bool) {
|
||||
set.RLock()
|
||||
for elem := range set.s {
|
||||
func (s *threadSafeSet[T]) Each(cb func(T) bool) {
|
||||
s.RLock()
|
||||
for elem := range s.uss {
|
||||
if cb(elem) {
|
||||
break
|
||||
}
|
||||
}
|
||||
set.RUnlock()
|
||||
s.RUnlock()
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) Iter() <-chan interface{} {
|
||||
ch := make(chan interface{})
|
||||
func (s *threadSafeSet[T]) Iter() <-chan T {
|
||||
ch := make(chan T)
|
||||
go func() {
|
||||
set.RLock()
|
||||
s.RLock()
|
||||
|
||||
for elem := range set.s {
|
||||
for elem := range s.uss {
|
||||
ch <- elem
|
||||
}
|
||||
close(ch)
|
||||
set.RUnlock()
|
||||
s.RUnlock()
|
||||
}()
|
||||
|
||||
return ch
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) Iterator() *Iterator {
|
||||
iterator, ch, stopCh := newIterator()
|
||||
func (s *threadSafeSet[T]) Iterator() *Iterator[T] {
|
||||
iterator, ch, stopCh := newIterator[T]()
|
||||
|
||||
go func() {
|
||||
set.RLock()
|
||||
s.RLock()
|
||||
L:
|
||||
for elem := range set.s {
|
||||
for elem := range s.uss {
|
||||
select {
|
||||
case <-stopCh:
|
||||
break L
|
||||
|
@ -190,94 +193,95 @@ func (set *threadSafeSet) Iterator() *Iterator {
|
|||
}
|
||||
}
|
||||
close(ch)
|
||||
set.RUnlock()
|
||||
s.RUnlock()
|
||||
}()
|
||||
|
||||
return iterator
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) Equal(other Set) bool {
|
||||
o := other.(*threadSafeSet)
|
||||
func (s *threadSafeSet[T]) Equal(other Set[T]) bool {
|
||||
o := other.(*threadSafeSet[T])
|
||||
|
||||
set.RLock()
|
||||
s.RLock()
|
||||
o.RLock()
|
||||
|
||||
ret := set.s.Equal(&o.s)
|
||||
set.RUnlock()
|
||||
ret := s.uss.Equal(&o.uss)
|
||||
s.RUnlock()
|
||||
o.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) Clone() Set {
|
||||
set.RLock()
|
||||
func (s *threadSafeSet[T]) Clone() Set[T] {
|
||||
s.RLock()
|
||||
|
||||
unsafeClone := set.s.Clone().(*threadUnsafeSet)
|
||||
ret := &threadSafeSet{s: *unsafeClone}
|
||||
set.RUnlock()
|
||||
unsafeClone := s.uss.Clone().(*threadUnsafeSet[T])
|
||||
ret := &threadSafeSet[T]{uss: *unsafeClone}
|
||||
s.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) String() string {
|
||||
set.RLock()
|
||||
ret := set.s.String()
|
||||
set.RUnlock()
|
||||
func (s *threadSafeSet[T]) String() string {
|
||||
s.RLock()
|
||||
ret := s.uss.String()
|
||||
s.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) PowerSet() Set {
|
||||
set.RLock()
|
||||
unsafePowerSet := set.s.PowerSet().(*threadUnsafeSet)
|
||||
set.RUnlock()
|
||||
func (s *threadSafeSet[T]) PowerSet() Set[any] {
|
||||
s.RLock()
|
||||
unsafePowerSet := s.uss.PowerSet().(*threadUnsafeSet[any])
|
||||
s.RUnlock()
|
||||
|
||||
ret := &threadSafeSet{s: newThreadUnsafeSet()}
|
||||
ret := &threadSafeSet[any]{uss: newThreadUnsafeSet[any]()}
|
||||
for subset := range unsafePowerSet.Iter() {
|
||||
unsafeSubset := subset.(*threadUnsafeSet)
|
||||
ret.Add(&threadSafeSet{s: *unsafeSubset})
|
||||
unsafeSubset := subset.(*threadUnsafeSet[any])
|
||||
ret.Add(&threadSafeSet[any]{uss: *unsafeSubset})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) Pop() interface{} {
|
||||
set.Lock()
|
||||
defer set.Unlock()
|
||||
return set.s.Pop()
|
||||
func (s *threadSafeSet[T]) Pop() any {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
return s.uss.Pop()
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) CartesianProduct(other Set) Set {
|
||||
o := other.(*threadSafeSet)
|
||||
func (s *threadSafeSet[T]) CartesianProduct(other Set[T]) Set[any] {
|
||||
o := other.(*threadSafeSet[T])
|
||||
|
||||
set.RLock()
|
||||
s.RLock()
|
||||
o.RLock()
|
||||
|
||||
unsafeCartProduct := set.s.CartesianProduct(&o.s).(*threadUnsafeSet)
|
||||
ret := &threadSafeSet{s: *unsafeCartProduct}
|
||||
set.RUnlock()
|
||||
unsafeCartProduct := s.uss.CartesianProduct(&o.uss).(*threadUnsafeSet[any])
|
||||
ret := &threadSafeSet[any]{uss: *unsafeCartProduct}
|
||||
|
||||
s.RUnlock()
|
||||
o.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) ToSlice() []interface{} {
|
||||
keys := make([]interface{}, 0, set.Cardinality())
|
||||
set.RLock()
|
||||
for elem := range set.s {
|
||||
func (s *threadSafeSet[T]) ToSlice() []T {
|
||||
keys := make([]T, 0, s.Cardinality())
|
||||
s.RLock()
|
||||
for elem := range s.uss {
|
||||
keys = append(keys, elem)
|
||||
}
|
||||
set.RUnlock()
|
||||
s.RUnlock()
|
||||
return keys
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) MarshalJSON() ([]byte, error) {
|
||||
set.RLock()
|
||||
b, err := set.s.MarshalJSON()
|
||||
set.RUnlock()
|
||||
func (s *threadSafeSet[T]) MarshalJSON() ([]byte, error) {
|
||||
s.RLock()
|
||||
b, err := s.uss.MarshalJSON()
|
||||
s.RUnlock()
|
||||
|
||||
return b, err
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) UnmarshalJSON(p []byte) error {
|
||||
set.RLock()
|
||||
err := set.s.UnmarshalJSON(p)
|
||||
set.RUnlock()
|
||||
func (s *threadSafeSet[T]) UnmarshalJSON(p []byte) error {
|
||||
s.RLock()
|
||||
err := s.uss.UnmarshalJSON(p)
|
||||
s.RUnlock()
|
||||
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1,287 +0,0 @@
|
|||
/*
|
||||
Open Source Initiative OSI - The MIT License (MIT):Licensing
|
||||
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
package mapset
|
||||
|
||||
import "sync"
|
||||
|
||||
type threadSafeSetGeneric[T comparable] struct {
|
||||
sync.RWMutex
|
||||
uss threadUnsafeSetGeneric[T]
|
||||
}
|
||||
|
||||
func newThreadSafeSetGeneric[T comparable]() threadSafeSetGeneric[T] {
|
||||
newUss := newThreadUnsafeSetGeneric[T]()
|
||||
return threadSafeSetGeneric[T]{
|
||||
uss: newUss,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *threadSafeSetGeneric[T]) Add(v T) bool {
|
||||
s.Lock()
|
||||
ret := s.uss.Add(v)
|
||||
s.Unlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (s *threadSafeSetGeneric[T]) Contains(v ...T) bool {
|
||||
s.RLock()
|
||||
ret := s.uss.Contains(v...)
|
||||
s.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (s *threadSafeSetGeneric[T]) IsSubset(other SetGeneric[T]) bool {
|
||||
o := other.(*threadSafeSetGeneric[T])
|
||||
|
||||
s.RLock()
|
||||
o.RLock()
|
||||
|
||||
ret := s.uss.IsSubset(&o.uss)
|
||||
s.RUnlock()
|
||||
o.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (s *threadSafeSetGeneric[T]) IsProperSubset(other SetGeneric[T]) bool {
|
||||
o := other.(*threadSafeSetGeneric[T])
|
||||
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
o.RLock()
|
||||
defer o.RUnlock()
|
||||
|
||||
return s.uss.IsProperSubset(&o.uss)
|
||||
}
|
||||
|
||||
func (s *threadSafeSetGeneric[T]) IsSuperset(other SetGeneric[T]) bool {
|
||||
return other.IsSubset(s)
|
||||
}
|
||||
|
||||
func (s *threadSafeSetGeneric[T]) IsProperSuperset(other SetGeneric[T]) bool {
|
||||
return other.IsProperSubset(s)
|
||||
}
|
||||
|
||||
func (s *threadSafeSetGeneric[T]) Union(other SetGeneric[T]) SetGeneric[T] {
|
||||
o := other.(*threadSafeSetGeneric[T])
|
||||
|
||||
s.RLock()
|
||||
o.RLock()
|
||||
|
||||
unsafeUnion := s.uss.Union(&o.uss).(*threadUnsafeSetGeneric[T])
|
||||
ret := &threadSafeSetGeneric[T]{uss: *unsafeUnion}
|
||||
s.RUnlock()
|
||||
o.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (s *threadSafeSetGeneric[T]) Intersect(other SetGeneric[T]) SetGeneric[T] {
|
||||
o := other.(*threadSafeSetGeneric[T])
|
||||
|
||||
s.RLock()
|
||||
o.RLock()
|
||||
|
||||
unsafeIntersection := s.uss.Intersect(&o.uss).(*threadUnsafeSetGeneric[T])
|
||||
ret := &threadSafeSetGeneric[T]{uss: *unsafeIntersection}
|
||||
s.RUnlock()
|
||||
o.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (s *threadSafeSetGeneric[T]) Difference(other SetGeneric[T]) SetGeneric[T] {
|
||||
o := other.(*threadSafeSetGeneric[T])
|
||||
|
||||
s.RLock()
|
||||
o.RLock()
|
||||
|
||||
unsafeDifference := s.uss.Difference(&o.uss).(*threadUnsafeSetGeneric[T])
|
||||
ret := &threadSafeSetGeneric[T]{uss: *unsafeDifference}
|
||||
s.RUnlock()
|
||||
o.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (s *threadSafeSetGeneric[T]) SymmetricDifference(other SetGeneric[T]) SetGeneric[T] {
|
||||
o := other.(*threadSafeSetGeneric[T])
|
||||
|
||||
s.RLock()
|
||||
o.RLock()
|
||||
|
||||
unsafeDifference := s.uss.SymmetricDifference(&o.uss).(*threadUnsafeSetGeneric[T])
|
||||
ret := &threadSafeSetGeneric[T]{uss: *unsafeDifference}
|
||||
s.RUnlock()
|
||||
o.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (s *threadSafeSetGeneric[T]) Clear() {
|
||||
s.Lock()
|
||||
s.uss = newThreadUnsafeSetGeneric[T]()
|
||||
s.Unlock()
|
||||
}
|
||||
|
||||
func (s *threadSafeSetGeneric[T]) Remove(v T) {
|
||||
s.Lock()
|
||||
delete(s.uss, v)
|
||||
s.Unlock()
|
||||
}
|
||||
|
||||
func (s *threadSafeSetGeneric[T]) Cardinality() int {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
return len(s.uss)
|
||||
}
|
||||
|
||||
func (s *threadSafeSetGeneric[T]) Each(cb func(T) bool) {
|
||||
s.RLock()
|
||||
for elem := range s.uss {
|
||||
if cb(elem) {
|
||||
break
|
||||
}
|
||||
}
|
||||
s.RUnlock()
|
||||
}
|
||||
|
||||
func (s *threadSafeSetGeneric[T]) Iter() <-chan T {
|
||||
ch := make(chan T)
|
||||
go func() {
|
||||
s.RLock()
|
||||
|
||||
for elem := range s.uss {
|
||||
ch <- elem
|
||||
}
|
||||
close(ch)
|
||||
s.RUnlock()
|
||||
}()
|
||||
|
||||
return ch
|
||||
}
|
||||
|
||||
func (s *threadSafeSetGeneric[T]) Iterator() *IteratorGeneric[T] {
|
||||
iterator, ch, stopCh := newIteratorGeneric[T]()
|
||||
|
||||
go func() {
|
||||
s.RLock()
|
||||
L:
|
||||
for elem := range s.uss {
|
||||
select {
|
||||
case <-stopCh:
|
||||
break L
|
||||
case ch <- elem:
|
||||
}
|
||||
}
|
||||
close(ch)
|
||||
s.RUnlock()
|
||||
}()
|
||||
|
||||
return iterator
|
||||
}
|
||||
|
||||
func (s *threadSafeSetGeneric[T]) Equal(other SetGeneric[T]) bool {
|
||||
o := other.(*threadSafeSetGeneric[T])
|
||||
|
||||
s.RLock()
|
||||
o.RLock()
|
||||
|
||||
ret := s.uss.Equal(&o.uss)
|
||||
s.RUnlock()
|
||||
o.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (s *threadSafeSetGeneric[T]) Clone() SetGeneric[T] {
|
||||
s.RLock()
|
||||
|
||||
unsafeClone := s.uss.Clone().(*threadUnsafeSetGeneric[T])
|
||||
ret := &threadSafeSetGeneric[T]{uss: *unsafeClone}
|
||||
s.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (s *threadSafeSetGeneric[T]) String() string {
|
||||
s.RLock()
|
||||
ret := s.uss.String()
|
||||
s.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (s *threadSafeSetGeneric[T]) PowerSet() SetGeneric[any] {
|
||||
s.RLock()
|
||||
unsafePowerSet := s.uss.PowerSet().(*threadUnsafeSetGeneric[any])
|
||||
s.RUnlock()
|
||||
|
||||
ret := &threadSafeSetGeneric[any]{uss: newThreadUnsafeSetGeneric[any]()}
|
||||
for subset := range unsafePowerSet.Iter() {
|
||||
unsafeSubset := subset.(*threadUnsafeSetGeneric[any])
|
||||
ret.Add(&threadSafeSetGeneric[any]{uss: *unsafeSubset})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (s *threadSafeSetGeneric[T]) Pop() any {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
return s.uss.Pop()
|
||||
}
|
||||
|
||||
func (s *threadSafeSetGeneric[T]) CartesianProduct(other SetGeneric[T]) SetGeneric[any] {
|
||||
o := other.(*threadSafeSetGeneric[T])
|
||||
|
||||
s.RLock()
|
||||
o.RLock()
|
||||
|
||||
unsafeCartProduct := s.uss.CartesianProduct(&o.uss).(*threadUnsafeSetGeneric[any])
|
||||
ret := &threadSafeSetGeneric[any]{uss: *unsafeCartProduct}
|
||||
|
||||
s.RUnlock()
|
||||
o.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (s *threadSafeSetGeneric[T]) ToSlice() []T {
|
||||
keys := make([]T, 0, s.Cardinality())
|
||||
s.RLock()
|
||||
for elem := range s.uss {
|
||||
keys = append(keys, elem)
|
||||
}
|
||||
s.RUnlock()
|
||||
return keys
|
||||
}
|
||||
|
||||
func (s *threadSafeSetGeneric[T]) MarshalJSON() ([]byte, error) {
|
||||
s.RLock()
|
||||
b, err := s.uss.MarshalJSON()
|
||||
s.RUnlock()
|
||||
|
||||
return b, err
|
||||
}
|
||||
|
||||
func (s *threadSafeSetGeneric[T]) UnmarshalJSON(p []byte) error {
|
||||
s.RLock()
|
||||
err := s.uss.UnmarshalJSON(p)
|
||||
s.RUnlock()
|
||||
|
||||
return err
|
||||
}
|
|
@ -39,7 +39,7 @@ const N = 1000
|
|||
func Test_AddConcurrent(t *testing.T) {
|
||||
runtime.GOMAXPROCS(2)
|
||||
|
||||
s := NewSetGeneric[int]()
|
||||
s := NewSet[int]()
|
||||
ints := rand.Perm(N)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
@ -62,7 +62,7 @@ func Test_AddConcurrent(t *testing.T) {
|
|||
func Test_CardinalityConcurrent(t *testing.T) {
|
||||
runtime.GOMAXPROCS(2)
|
||||
|
||||
s := NewSetGeneric[int]()
|
||||
s := NewSet[int]()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
|
@ -86,7 +86,7 @@ func Test_CardinalityConcurrent(t *testing.T) {
|
|||
func Test_ClearConcurrent(t *testing.T) {
|
||||
runtime.GOMAXPROCS(2)
|
||||
|
||||
s := NewSetGeneric[int]()
|
||||
s := NewSet[int]()
|
||||
ints := rand.Perm(N)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
@ -107,7 +107,7 @@ func Test_ClearConcurrent(t *testing.T) {
|
|||
func Test_CloneConcurrent(t *testing.T) {
|
||||
runtime.GOMAXPROCS(2)
|
||||
|
||||
s := NewSetGeneric[int]()
|
||||
s := NewSet[int]()
|
||||
ints := rand.Perm(N)
|
||||
|
||||
for _, v := range ints {
|
||||
|
@ -129,7 +129,7 @@ func Test_CloneConcurrent(t *testing.T) {
|
|||
func Test_ContainsConcurrent(t *testing.T) {
|
||||
runtime.GOMAXPROCS(2)
|
||||
|
||||
s := NewSetGeneric[int]()
|
||||
s := NewSet[int]()
|
||||
ints := rand.Perm(N)
|
||||
integers := make([]int, 0)
|
||||
for _, v := range ints {
|
||||
|
@ -151,7 +151,7 @@ func Test_ContainsConcurrent(t *testing.T) {
|
|||
func Test_DifferenceConcurrent(t *testing.T) {
|
||||
runtime.GOMAXPROCS(2)
|
||||
|
||||
s, ss := NewSetGeneric[int](), NewSetGeneric[int]()
|
||||
s, ss := NewSet[int](), NewSet[int]()
|
||||
ints := rand.Perm(N)
|
||||
for _, v := range ints {
|
||||
s.Add(v)
|
||||
|
@ -172,7 +172,7 @@ func Test_DifferenceConcurrent(t *testing.T) {
|
|||
func Test_EqualConcurrent(t *testing.T) {
|
||||
runtime.GOMAXPROCS(2)
|
||||
|
||||
s, ss := NewSetGeneric[int](), NewSetGeneric[int]()
|
||||
s, ss := NewSet[int](), NewSet[int]()
|
||||
ints := rand.Perm(N)
|
||||
for _, v := range ints {
|
||||
s.Add(v)
|
||||
|
@ -193,7 +193,7 @@ func Test_EqualConcurrent(t *testing.T) {
|
|||
func Test_IntersectConcurrent(t *testing.T) {
|
||||
runtime.GOMAXPROCS(2)
|
||||
|
||||
s, ss := NewSetGeneric[int](), NewSetGeneric[int]()
|
||||
s, ss := NewSet[int](), NewSet[int]()
|
||||
ints := rand.Perm(N)
|
||||
for _, v := range ints {
|
||||
s.Add(v)
|
||||
|
@ -214,7 +214,7 @@ func Test_IntersectConcurrent(t *testing.T) {
|
|||
func Test_IsSubsetConcurrent(t *testing.T) {
|
||||
runtime.GOMAXPROCS(2)
|
||||
|
||||
s, ss := NewSetGeneric[int](), NewSetGeneric[int]()
|
||||
s, ss := NewSet[int](), NewSet[int]()
|
||||
ints := rand.Perm(N)
|
||||
for _, v := range ints {
|
||||
s.Add(v)
|
||||
|
@ -235,7 +235,7 @@ func Test_IsSubsetConcurrent(t *testing.T) {
|
|||
func Test_IsProperSubsetConcurrent(t *testing.T) {
|
||||
runtime.GOMAXPROCS(2)
|
||||
|
||||
s, ss := NewSetGeneric[int](), NewSetGeneric[int]()
|
||||
s, ss := NewSet[int](), NewSet[int]()
|
||||
ints := rand.Perm(N)
|
||||
for _, v := range ints {
|
||||
s.Add(v)
|
||||
|
@ -256,7 +256,7 @@ func Test_IsProperSubsetConcurrent(t *testing.T) {
|
|||
func Test_IsSupersetConcurrent(t *testing.T) {
|
||||
runtime.GOMAXPROCS(2)
|
||||
|
||||
s, ss := NewSetGeneric[int](), NewSetGeneric[int]()
|
||||
s, ss := NewSet[int](), NewSet[int]()
|
||||
ints := rand.Perm(N)
|
||||
for _, v := range ints {
|
||||
s.Add(v)
|
||||
|
@ -277,7 +277,7 @@ func Test_IsSupersetConcurrent(t *testing.T) {
|
|||
func Test_IsProperSupersetConcurrent(t *testing.T) {
|
||||
runtime.GOMAXPROCS(2)
|
||||
|
||||
s, ss := NewSetGeneric[int](), NewSetGeneric[int]()
|
||||
s, ss := NewSet[int](), NewSet[int]()
|
||||
ints := rand.Perm(N)
|
||||
for _, v := range ints {
|
||||
s.Add(v)
|
||||
|
@ -299,7 +299,7 @@ func Test_EachConcurrent(t *testing.T) {
|
|||
runtime.GOMAXPROCS(2)
|
||||
concurrent := 10
|
||||
|
||||
s := NewSetGeneric[int]()
|
||||
s := NewSet[int]()
|
||||
ints := rand.Perm(N)
|
||||
for _, v := range ints {
|
||||
s.Add(v)
|
||||
|
@ -327,7 +327,7 @@ func Test_EachConcurrent(t *testing.T) {
|
|||
func Test_IterConcurrent(t *testing.T) {
|
||||
runtime.GOMAXPROCS(2)
|
||||
|
||||
s := NewSetGeneric[int]()
|
||||
s := NewSet[int]()
|
||||
ints := rand.Perm(N)
|
||||
for _, v := range ints {
|
||||
s.Add(v)
|
||||
|
@ -360,7 +360,7 @@ func Test_IterConcurrent(t *testing.T) {
|
|||
func Test_RemoveConcurrent(t *testing.T) {
|
||||
runtime.GOMAXPROCS(2)
|
||||
|
||||
s := NewSetGeneric[int]()
|
||||
s := NewSet[int]()
|
||||
ints := rand.Perm(N)
|
||||
for _, v := range ints {
|
||||
s.Add(v)
|
||||
|
@ -384,7 +384,7 @@ func Test_RemoveConcurrent(t *testing.T) {
|
|||
func Test_StringConcurrent(t *testing.T) {
|
||||
runtime.GOMAXPROCS(2)
|
||||
|
||||
s := NewSetGeneric[int]()
|
||||
s := NewSet[int]()
|
||||
ints := rand.Perm(N)
|
||||
for _, v := range ints {
|
||||
s.Add(v)
|
||||
|
@ -404,7 +404,7 @@ func Test_StringConcurrent(t *testing.T) {
|
|||
func Test_SymmetricDifferenceConcurrent(t *testing.T) {
|
||||
runtime.GOMAXPROCS(2)
|
||||
|
||||
s, ss := NewSetGeneric[int](), NewSetGeneric[int]()
|
||||
s, ss := NewSet[int](), NewSet[int]()
|
||||
ints := rand.Perm(N)
|
||||
for _, v := range ints {
|
||||
s.Add(v)
|
||||
|
@ -425,7 +425,7 @@ func Test_SymmetricDifferenceConcurrent(t *testing.T) {
|
|||
func Test_ToSlice(t *testing.T) {
|
||||
runtime.GOMAXPROCS(2)
|
||||
|
||||
s := NewSetGeneric[int]()
|
||||
s := NewSet[int]()
|
||||
ints := rand.Perm(N)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
@ -456,7 +456,7 @@ func Test_ToSliceDeadlock(t *testing.T) {
|
|||
runtime.GOMAXPROCS(2)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
set := NewSetGeneric[int]()
|
||||
set := NewSet[int]()
|
||||
workers := 10
|
||||
wg.Add(workers)
|
||||
for i := 1; i <= workers; i++ {
|
||||
|
@ -473,7 +473,7 @@ func Test_ToSliceDeadlock(t *testing.T) {
|
|||
|
||||
func Test_UnmarshalJSON(t *testing.T) {
|
||||
s := []byte(`["test", 1, 2, 3]`) //,["4,5,6"]]`)
|
||||
expected := NewSetFromSliceGeneric[any](
|
||||
expected := NewSetFromSlice[any](
|
||||
[]any{
|
||||
json.Number("1"),
|
||||
json.Number("2"),
|
||||
|
@ -481,7 +481,7 @@ func Test_UnmarshalJSON(t *testing.T) {
|
|||
"test",
|
||||
},
|
||||
)
|
||||
actual := NewSetGeneric[any]()
|
||||
actual := NewSet[any]()
|
||||
err := json.Unmarshal(s, actual)
|
||||
if err != nil {
|
||||
t.Errorf("Error should be nil: %v", err)
|
||||
|
@ -493,7 +493,7 @@ func Test_UnmarshalJSON(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_MarshalJSON(t *testing.T) {
|
||||
expected := NewSetFromSliceGeneric[any](
|
||||
expected := NewSetFromSlice[any](
|
||||
[]any{
|
||||
json.Number("1"),
|
||||
"test",
|
||||
|
@ -501,7 +501,7 @@ func Test_MarshalJSON(t *testing.T) {
|
|||
)
|
||||
|
||||
b, err := json.Marshal(
|
||||
NewSetFromSliceGeneric[any](
|
||||
NewSetFromSlice[any](
|
||||
[]any{
|
||||
1,
|
||||
"test",
|
||||
|
@ -512,7 +512,7 @@ func Test_MarshalJSON(t *testing.T) {
|
|||
t.Errorf("Error should be nil: %v", err)
|
||||
}
|
||||
|
||||
actual := NewSetGeneric[any]()
|
||||
actual := NewSet[any]()
|
||||
err = json.Unmarshal(b, actual)
|
||||
if err != nil {
|
||||
t.Errorf("Error should be nil: %v", err)
|
||||
|
|
348
threadunsafe.go
348
threadunsafe.go
|
@ -26,27 +26,21 @@ SOFTWARE.
|
|||
package mapset
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"encoding/json"
|
||||
"bytes"
|
||||
)
|
||||
|
||||
type threadUnsafeSet map[interface{}]struct{}
|
||||
|
||||
// An OrderedPair represents a 2-tuple of values.
|
||||
type OrderedPair struct {
|
||||
First interface{}
|
||||
Second interface{}
|
||||
}
|
||||
|
||||
func newThreadUnsafeSet() threadUnsafeSet {
|
||||
return make(threadUnsafeSet)
|
||||
type OrderedPair[T comparable] struct {
|
||||
First T
|
||||
Second T
|
||||
}
|
||||
|
||||
// Equal says whether two 2-tuples contain the same values in the same order.
|
||||
func (pair *OrderedPair) Equal(other OrderedPair) bool {
|
||||
func (pair *OrderedPair[T]) Equal(other OrderedPair[T]) bool {
|
||||
if pair.First == other.First &&
|
||||
pair.Second == other.Second {
|
||||
return true
|
||||
|
@ -55,31 +49,109 @@ func (pair *OrderedPair) Equal(other OrderedPair) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) Add(i interface{}) bool {
|
||||
_, found := (*set)[i]
|
||||
// String outputs a 2-tuple in the form "(A, B)".
|
||||
func (pair OrderedPair[T]) String() string {
|
||||
return fmt.Sprintf("(%v, %v)", pair.First, pair.Second)
|
||||
}
|
||||
|
||||
type threadUnsafeSet[T comparable] map[T]struct{}
|
||||
|
||||
// // An OrderedPair represents a 2-tuple of values.
|
||||
// type OrderedPair struct {
|
||||
// First interface{}
|
||||
// Second interface{}
|
||||
// }
|
||||
|
||||
// Assert concrete type:threadUnsafeSet adheres to Set interface.
|
||||
var _ Set[string] = (*threadUnsafeSet[string])(nil)
|
||||
|
||||
func newThreadUnsafeSet[T comparable]() threadUnsafeSet[T] {
|
||||
return make(threadUnsafeSet[T])
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSet[T]) Add(v T) bool {
|
||||
_, found := (*s)[v]
|
||||
if found {
|
||||
return false //False if it existed already
|
||||
}
|
||||
|
||||
(*set)[i] = struct{}{}
|
||||
(*s)[v] = struct{}{}
|
||||
return true
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) Contains(i ...interface{}) bool {
|
||||
for _, val := range i {
|
||||
if _, ok := (*set)[val]; !ok {
|
||||
func (s *threadUnsafeSet[T]) Cardinality() int {
|
||||
return len(*s)
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSet[T]) CartesianProduct(other Set[T]) Set[any] {
|
||||
o := other.(*threadUnsafeSet[T])
|
||||
|
||||
// NOTE: limitation with Go s or of my knowledge of Go s?
|
||||
|
||||
// I can't seem to declare this without an instantiation cycle.
|
||||
//cartProduct := NewThreadUnsafeSet[OrderedPair[T]]()
|
||||
|
||||
// So here is my crime against humanity.
|
||||
cartProduct := NewThreadUnsafeSet[any]()
|
||||
|
||||
for i := range *s {
|
||||
for j := range *o {
|
||||
elem := OrderedPair[T]{First: i, Second: j}
|
||||
cartProduct.Add(elem)
|
||||
}
|
||||
}
|
||||
|
||||
return cartProduct
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSet[T]) Clear() {
|
||||
*s = newThreadUnsafeSet[T]()
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSet[T]) Clone() Set[T] {
|
||||
clonedSet := newThreadUnsafeSet[T]()
|
||||
for elem := range *s {
|
||||
clonedSet.Add(elem)
|
||||
}
|
||||
return &clonedSet
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSet[T]) Contains(v ...T) bool {
|
||||
for _, val := range v {
|
||||
if _, ok := (*s)[val]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) IsSubset(other Set) bool {
|
||||
_ = other.(*threadUnsafeSet)
|
||||
if set.Cardinality() > other.Cardinality() {
|
||||
func (s *threadUnsafeSet[T]) Difference(other Set[T]) Set[T] {
|
||||
_ = other.(*threadUnsafeSet[T])
|
||||
|
||||
diff := newThreadUnsafeSet[T]()
|
||||
for elem := range *s {
|
||||
if !other.Contains(elem) {
|
||||
diff.Add(elem)
|
||||
}
|
||||
}
|
||||
return &diff
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSet[T]) Each(cb func(T) bool) {
|
||||
for elem := range *s {
|
||||
if cb(elem) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSet[T]) Equal(other Set[T]) bool {
|
||||
_ = other.(*threadUnsafeSet[T])
|
||||
|
||||
if s.Cardinality() != other.Cardinality() {
|
||||
return false
|
||||
}
|
||||
for elem := range *set {
|
||||
for elem := range *s {
|
||||
if !other.Contains(elem) {
|
||||
return false
|
||||
}
|
||||
|
@ -87,46 +159,20 @@ func (set *threadUnsafeSet) IsSubset(other Set) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) IsProperSubset(other Set) bool {
|
||||
return set.IsSubset(other) && !set.Equal(other)
|
||||
}
|
||||
func (s *threadUnsafeSet[T]) Intersect(other Set[T]) Set[T] {
|
||||
o := other.(*threadUnsafeSet[T])
|
||||
|
||||
func (set *threadUnsafeSet) IsSuperset(other Set) bool {
|
||||
return other.IsSubset(set)
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) IsProperSuperset(other Set) bool {
|
||||
return set.IsSuperset(other) && !set.Equal(other)
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) Union(other Set) Set {
|
||||
o := other.(*threadUnsafeSet)
|
||||
|
||||
unionedSet := newThreadUnsafeSet()
|
||||
|
||||
for elem := range *set {
|
||||
unionedSet.Add(elem)
|
||||
}
|
||||
for elem := range *o {
|
||||
unionedSet.Add(elem)
|
||||
}
|
||||
return &unionedSet
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) Intersect(other Set) Set {
|
||||
o := other.(*threadUnsafeSet)
|
||||
|
||||
intersection := newThreadUnsafeSet()
|
||||
intersection := newThreadUnsafeSet[T]()
|
||||
// loop over smaller set
|
||||
if set.Cardinality() < other.Cardinality() {
|
||||
for elem := range *set {
|
||||
if s.Cardinality() < other.Cardinality() {
|
||||
for elem := range *s {
|
||||
if other.Contains(elem) {
|
||||
intersection.Add(elem)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for elem := range *o {
|
||||
if set.Contains(elem) {
|
||||
if s.Contains(elem) {
|
||||
intersection.Add(elem)
|
||||
}
|
||||
}
|
||||
|
@ -134,50 +180,35 @@ func (set *threadUnsafeSet) Intersect(other Set) Set {
|
|||
return &intersection
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) Difference(other Set) Set {
|
||||
_ = other.(*threadUnsafeSet)
|
||||
func (s *threadUnsafeSet[T]) IsProperSubset(other Set[T]) bool {
|
||||
return s.IsSubset(other) && !s.Equal(other)
|
||||
}
|
||||
|
||||
difference := newThreadUnsafeSet()
|
||||
for elem := range *set {
|
||||
func (s *threadUnsafeSet[T]) IsProperSuperset(other Set[T]) bool {
|
||||
return s.IsSuperset(other) && !s.Equal(other)
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSet[T]) IsSubset(other Set[T]) bool {
|
||||
_ = other.(*threadUnsafeSet[T])
|
||||
if s.Cardinality() > other.Cardinality() {
|
||||
return false
|
||||
}
|
||||
for elem := range *s {
|
||||
if !other.Contains(elem) {
|
||||
difference.Add(elem)
|
||||
return false
|
||||
}
|
||||
}
|
||||
return &difference
|
||||
return true
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) SymmetricDifference(other Set) Set {
|
||||
_ = other.(*threadUnsafeSet)
|
||||
|
||||
aDiff := set.Difference(other)
|
||||
bDiff := other.Difference(set)
|
||||
return aDiff.Union(bDiff)
|
||||
func (s *threadUnsafeSet[T]) IsSuperset(other Set[T]) bool {
|
||||
return other.IsSubset(s)
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) Clear() {
|
||||
*set = newThreadUnsafeSet()
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) Remove(i interface{}) {
|
||||
delete(*set, i)
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) Cardinality() int {
|
||||
return len(*set)
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) Each(cb func(interface{}) bool) {
|
||||
for elem := range *set {
|
||||
if cb(elem) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) Iter() <-chan interface{} {
|
||||
ch := make(chan interface{})
|
||||
func (s *threadUnsafeSet[T]) Iter() <-chan T {
|
||||
ch := make(chan T)
|
||||
go func() {
|
||||
for elem := range *set {
|
||||
for elem := range *s {
|
||||
ch <- elem
|
||||
}
|
||||
close(ch)
|
||||
|
@ -186,12 +217,12 @@ func (set *threadUnsafeSet) Iter() <-chan interface{} {
|
|||
return ch
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) Iterator() *Iterator {
|
||||
iterator, ch, stopCh := newIterator()
|
||||
func (s *threadUnsafeSet[T]) Iterator() *Iterator[T] {
|
||||
iterator, ch, stopCh := newIterator[T]()
|
||||
|
||||
go func() {
|
||||
L:
|
||||
for elem := range *set {
|
||||
for elem := range *s {
|
||||
select {
|
||||
case <-stopCh:
|
||||
break L
|
||||
|
@ -204,67 +235,34 @@ func (set *threadUnsafeSet) Iterator() *Iterator {
|
|||
return iterator
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) Equal(other Set) bool {
|
||||
_ = other.(*threadUnsafeSet)
|
||||
|
||||
if set.Cardinality() != other.Cardinality() {
|
||||
return false
|
||||
}
|
||||
for elem := range *set {
|
||||
if !other.Contains(elem) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) Clone() Set {
|
||||
clonedSet := newThreadUnsafeSet()
|
||||
for elem := range *set {
|
||||
clonedSet.Add(elem)
|
||||
}
|
||||
return &clonedSet
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) String() string {
|
||||
items := make([]string, 0, len(*set))
|
||||
|
||||
for elem := range *set {
|
||||
items = append(items, fmt.Sprintf("%v", elem))
|
||||
}
|
||||
return fmt.Sprintf("Set{%s}", strings.Join(items, ", "))
|
||||
}
|
||||
|
||||
// String outputs a 2-tuple in the form "(A, B)".
|
||||
func (pair OrderedPair) String() string {
|
||||
return fmt.Sprintf("(%v, %v)", pair.First, pair.Second)
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) Pop() interface{} {
|
||||
for item := range *set {
|
||||
delete(*set, item)
|
||||
// TODO: how can we make this properly , return T but can't return nil.
|
||||
func (s *threadUnsafeSet[T]) Pop() any {
|
||||
for item := range *s {
|
||||
delete(*s, item)
|
||||
return item
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) PowerSet() Set {
|
||||
powSet := NewThreadUnsafeSet()
|
||||
nullset := newThreadUnsafeSet()
|
||||
func (s *threadUnsafeSet[T]) PowerSet() Set[any] {
|
||||
// The type must be any comparable so we have to dumb down to any.
|
||||
powSet := NewThreadUnsafeSet[any]()
|
||||
|
||||
nullset := newThreadUnsafeSet[T]()
|
||||
powSet.Add(&nullset)
|
||||
|
||||
for es := range *set {
|
||||
u := newThreadUnsafeSet()
|
||||
for es := range *s {
|
||||
u := newThreadUnsafeSet[any]()
|
||||
j := powSet.Iter()
|
||||
for er := range j {
|
||||
p := newThreadUnsafeSet()
|
||||
p := newThreadUnsafeSet[T]()
|
||||
if reflect.TypeOf(er).Name() == "" {
|
||||
k := er.(*threadUnsafeSet)
|
||||
k := er.(*threadUnsafeSet[T])
|
||||
for ek := range *(k) {
|
||||
p.Add(ek)
|
||||
}
|
||||
} else {
|
||||
p.Add(er)
|
||||
p.Add(er.(T))
|
||||
}
|
||||
p.Add(es)
|
||||
u.Add(&p)
|
||||
|
@ -276,34 +274,55 @@ func (set *threadUnsafeSet) PowerSet() Set {
|
|||
return powSet
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) CartesianProduct(other Set) Set {
|
||||
o := other.(*threadUnsafeSet)
|
||||
cartProduct := NewThreadUnsafeSet()
|
||||
|
||||
for i := range *set {
|
||||
for j := range *o {
|
||||
elem := OrderedPair{First: i, Second: j}
|
||||
cartProduct.Add(elem)
|
||||
}
|
||||
}
|
||||
|
||||
return cartProduct
|
||||
func (s *threadUnsafeSet[T]) Remove(v T) {
|
||||
delete(*s, v)
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) ToSlice() []interface{} {
|
||||
keys := make([]interface{}, 0, set.Cardinality())
|
||||
for elem := range *set {
|
||||
func (s *threadUnsafeSet[T]) String() string {
|
||||
items := make([]string, 0, len(*s))
|
||||
|
||||
for elem := range *s {
|
||||
items = append(items, fmt.Sprintf("%v", elem))
|
||||
}
|
||||
return fmt.Sprintf("Set{%s}", strings.Join(items, ", "))
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSet[T]) SymmetricDifference(other Set[T]) Set[T] {
|
||||
_ = other.(*threadUnsafeSet[T])
|
||||
|
||||
a := s.Difference(other)
|
||||
b := other.Difference(s)
|
||||
return a.Union(b)
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSet[T]) ToSlice() []T {
|
||||
keys := make([]T, 0, s.Cardinality())
|
||||
for elem := range *s {
|
||||
keys = append(keys, elem)
|
||||
}
|
||||
|
||||
return keys
|
||||
}
|
||||
|
||||
// MarshalJSON creates a JSON array from the set, it marshals all elements
|
||||
func (set *threadUnsafeSet) MarshalJSON() ([]byte, error) {
|
||||
items := make([]string, 0, set.Cardinality())
|
||||
func (s *threadUnsafeSet[T]) Union(other Set[T]) Set[T] {
|
||||
o := other.(*threadUnsafeSet[T])
|
||||
|
||||
for elem := range *set {
|
||||
unionedSet := newThreadUnsafeSet[T]()
|
||||
|
||||
for elem := range *s {
|
||||
unionedSet.Add(elem)
|
||||
}
|
||||
for elem := range *o {
|
||||
unionedSet.Add(elem)
|
||||
}
|
||||
return &unionedSet
|
||||
}
|
||||
|
||||
// MarshalJSON creates a JSON array from the set, it marshals all elements
|
||||
func (s *threadUnsafeSet[T]) MarshalJSON() ([]byte, error) {
|
||||
items := make([]string, 0, s.Cardinality())
|
||||
|
||||
for elem := range *s {
|
||||
b, err := json.Marshal(elem)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -317,8 +336,8 @@ func (set *threadUnsafeSet) MarshalJSON() ([]byte, error) {
|
|||
|
||||
// UnmarshalJSON recreates a set from a JSON array, it only decodes
|
||||
// primitive types. Numbers are decoded as json.Number.
|
||||
func (set *threadUnsafeSet) UnmarshalJSON(b []byte) error {
|
||||
var i []interface{}
|
||||
func (s *threadUnsafeSet[T]) UnmarshalJSON(b []byte) error {
|
||||
var i []any
|
||||
|
||||
d := json.NewDecoder(bytes.NewReader(b))
|
||||
d.UseNumber()
|
||||
|
@ -329,12 +348,13 @@ func (set *threadUnsafeSet) UnmarshalJSON(b []byte) error {
|
|||
|
||||
for _, v := range i {
|
||||
switch t := v.(type) {
|
||||
case []interface{}, map[string]interface{}:
|
||||
continue
|
||||
case T:
|
||||
s.Add(t)
|
||||
default:
|
||||
set.Add(t)
|
||||
// anything else must be skipped.
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
|
@ -1,360 +0,0 @@
|
|||
/*
|
||||
Open Source Initiative OSI - The MIT License (MIT):Licensing
|
||||
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
package mapset
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"encoding/json"
|
||||
"bytes"
|
||||
)
|
||||
|
||||
// An OrderedPairGeneric represents a 2-tuple of values.
|
||||
type OrderedPairGeneric[T comparable] struct {
|
||||
First T
|
||||
Second T
|
||||
}
|
||||
|
||||
// Equal says whether two 2-tuples contain the same values in the same order.
|
||||
func (pair *OrderedPairGeneric[T]) Equal(other OrderedPairGeneric[T]) bool {
|
||||
if pair.First == other.First &&
|
||||
pair.Second == other.Second {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// String outputs a 2-tuple in the form "(A, B)".
|
||||
func (pair OrderedPairGeneric[T]) String() string {
|
||||
return fmt.Sprintf("(%v, %v)", pair.First, pair.Second)
|
||||
}
|
||||
|
||||
type threadUnsafeSetGeneric[T comparable] map[T]struct{}
|
||||
|
||||
// // An OrderedPair represents a 2-tuple of values.
|
||||
// type OrderedPair struct {
|
||||
// First interface{}
|
||||
// Second interface{}
|
||||
// }
|
||||
|
||||
// Assert concrete type:threadUnsafeSetGeneric adheres to SetGeneric interface.
|
||||
var _ SetGeneric[string] = (*threadUnsafeSetGeneric[string])(nil)
|
||||
|
||||
func newThreadUnsafeSetGeneric[T comparable]() threadUnsafeSetGeneric[T] {
|
||||
return make(threadUnsafeSetGeneric[T])
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSetGeneric[T]) Add(v T) bool {
|
||||
_, found := (*s)[v]
|
||||
if found {
|
||||
return false //False if it existed already
|
||||
}
|
||||
|
||||
(*s)[v] = struct{}{}
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSetGeneric[T]) Cardinality() int {
|
||||
return len(*s)
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSetGeneric[T]) CartesianProduct(other SetGeneric[T]) SetGeneric[any] {
|
||||
o := other.(*threadUnsafeSetGeneric[T])
|
||||
|
||||
// NOTE: limitation with Go generics or of my knowledge of Go generics?
|
||||
|
||||
// I can't seem to declare this without an instantiation cycle.
|
||||
//cartProduct := NewThreadUnsafeSetGeneric[OrderedPairGeneric[T]]()
|
||||
|
||||
// So here is my crime against humanity.
|
||||
cartProduct := NewThreadUnsafeSetGeneric[any]()
|
||||
|
||||
for i := range *s {
|
||||
for j := range *o {
|
||||
elem := OrderedPairGeneric[T]{First: i, Second: j}
|
||||
cartProduct.Add(elem)
|
||||
}
|
||||
}
|
||||
|
||||
return cartProduct
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSetGeneric[T]) Clear() {
|
||||
*s = newThreadUnsafeSetGeneric[T]()
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSetGeneric[T]) Clone() SetGeneric[T] {
|
||||
clonedSet := newThreadUnsafeSetGeneric[T]()
|
||||
for elem := range *s {
|
||||
clonedSet.Add(elem)
|
||||
}
|
||||
return &clonedSet
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSetGeneric[T]) Contains(v ...T) bool {
|
||||
for _, val := range v {
|
||||
if _, ok := (*s)[val]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSetGeneric[T]) Difference(other SetGeneric[T]) SetGeneric[T] {
|
||||
_ = other.(*threadUnsafeSetGeneric[T])
|
||||
|
||||
diff := newThreadUnsafeSetGeneric[T]()
|
||||
for elem := range *s {
|
||||
if !other.Contains(elem) {
|
||||
diff.Add(elem)
|
||||
}
|
||||
}
|
||||
return &diff
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSetGeneric[T]) Each(cb func(T) bool) {
|
||||
for elem := range *s {
|
||||
if cb(elem) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSetGeneric[T]) Equal(other SetGeneric[T]) bool {
|
||||
_ = other.(*threadUnsafeSetGeneric[T])
|
||||
|
||||
if s.Cardinality() != other.Cardinality() {
|
||||
return false
|
||||
}
|
||||
for elem := range *s {
|
||||
if !other.Contains(elem) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSetGeneric[T]) Intersect(other SetGeneric[T]) SetGeneric[T] {
|
||||
o := other.(*threadUnsafeSetGeneric[T])
|
||||
|
||||
intersection := newThreadUnsafeSetGeneric[T]()
|
||||
// loop over smaller set
|
||||
if s.Cardinality() < other.Cardinality() {
|
||||
for elem := range *s {
|
||||
if other.Contains(elem) {
|
||||
intersection.Add(elem)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for elem := range *o {
|
||||
if s.Contains(elem) {
|
||||
intersection.Add(elem)
|
||||
}
|
||||
}
|
||||
}
|
||||
return &intersection
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSetGeneric[T]) IsProperSubset(other SetGeneric[T]) bool {
|
||||
return s.IsSubset(other) && !s.Equal(other)
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSetGeneric[T]) IsProperSuperset(other SetGeneric[T]) bool {
|
||||
return s.IsSuperset(other) && !s.Equal(other)
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSetGeneric[T]) IsSubset(other SetGeneric[T]) bool {
|
||||
_ = other.(*threadUnsafeSetGeneric[T])
|
||||
if s.Cardinality() > other.Cardinality() {
|
||||
return false
|
||||
}
|
||||
for elem := range *s {
|
||||
if !other.Contains(elem) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSetGeneric[T]) IsSuperset(other SetGeneric[T]) bool {
|
||||
return other.IsSubset(s)
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSetGeneric[T]) Iter() <-chan T {
|
||||
ch := make(chan T)
|
||||
go func() {
|
||||
for elem := range *s {
|
||||
ch <- elem
|
||||
}
|
||||
close(ch)
|
||||
}()
|
||||
|
||||
return ch
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSetGeneric[T]) Iterator() *IteratorGeneric[T] {
|
||||
iterator, ch, stopCh := newIteratorGeneric[T]()
|
||||
|
||||
go func() {
|
||||
L:
|
||||
for elem := range *s {
|
||||
select {
|
||||
case <-stopCh:
|
||||
break L
|
||||
case ch <- elem:
|
||||
}
|
||||
}
|
||||
close(ch)
|
||||
}()
|
||||
|
||||
return iterator
|
||||
}
|
||||
|
||||
// TODO: how can we make this properly generic, return T but can't return nil.
|
||||
func (s *threadUnsafeSetGeneric[T]) Pop() any {
|
||||
for item := range *s {
|
||||
delete(*s, item)
|
||||
return item
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSetGeneric[T]) PowerSet() SetGeneric[any] {
|
||||
// The type must be any comparable so we have to dumb down to any.
|
||||
powSet := NewThreadUnsafeSetGeneric[any]()
|
||||
|
||||
nullset := newThreadUnsafeSetGeneric[T]()
|
||||
powSet.Add(&nullset)
|
||||
|
||||
for es := range *s {
|
||||
u := newThreadUnsafeSetGeneric[any]()
|
||||
j := powSet.Iter()
|
||||
for er := range j {
|
||||
p := newThreadUnsafeSetGeneric[T]()
|
||||
if reflect.TypeOf(er).Name() == "" {
|
||||
k := er.(*threadUnsafeSetGeneric[T])
|
||||
for ek := range *(k) {
|
||||
p.Add(ek)
|
||||
}
|
||||
} else {
|
||||
p.Add(er.(T))
|
||||
}
|
||||
p.Add(es)
|
||||
u.Add(&p)
|
||||
}
|
||||
|
||||
powSet = powSet.Union(&u)
|
||||
}
|
||||
|
||||
return powSet
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSetGeneric[T]) Remove(v T) {
|
||||
delete(*s, v)
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSetGeneric[T]) String() string {
|
||||
items := make([]string, 0, len(*s))
|
||||
|
||||
for elem := range *s {
|
||||
items = append(items, fmt.Sprintf("%v", elem))
|
||||
}
|
||||
return fmt.Sprintf("Set{%s}", strings.Join(items, ", "))
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSetGeneric[T]) SymmetricDifference(other SetGeneric[T]) SetGeneric[T] {
|
||||
_ = other.(*threadUnsafeSetGeneric[T])
|
||||
|
||||
a := s.Difference(other)
|
||||
b := other.Difference(s)
|
||||
return a.Union(b)
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSetGeneric[T]) ToSlice() []T {
|
||||
keys := make([]T, 0, s.Cardinality())
|
||||
for elem := range *s {
|
||||
keys = append(keys, elem)
|
||||
}
|
||||
|
||||
return keys
|
||||
}
|
||||
|
||||
func (s *threadUnsafeSetGeneric[T]) Union(other SetGeneric[T]) SetGeneric[T] {
|
||||
o := other.(*threadUnsafeSetGeneric[T])
|
||||
|
||||
unionedSet := newThreadUnsafeSetGeneric[T]()
|
||||
|
||||
for elem := range *s {
|
||||
unionedSet.Add(elem)
|
||||
}
|
||||
for elem := range *o {
|
||||
unionedSet.Add(elem)
|
||||
}
|
||||
return &unionedSet
|
||||
}
|
||||
|
||||
// MarshalJSON creates a JSON array from the set, it marshals all elements
|
||||
func (s *threadUnsafeSetGeneric[T]) MarshalJSON() ([]byte, error) {
|
||||
items := make([]string, 0, s.Cardinality())
|
||||
|
||||
for elem := range *s {
|
||||
b, err := json.Marshal(elem)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
items = append(items, string(b))
|
||||
}
|
||||
|
||||
return []byte(fmt.Sprintf("[%s]", strings.Join(items, ","))), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON recreates a set from a JSON array, it only decodes
|
||||
// primitive types. Numbers are decoded as json.Number.
|
||||
func (s *threadUnsafeSetGeneric[T]) UnmarshalJSON(b []byte) error {
|
||||
var i []any
|
||||
|
||||
d := json.NewDecoder(bytes.NewReader(b))
|
||||
d.UseNumber()
|
||||
err := d.Decode(&i)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, v := range i {
|
||||
switch t := v.(type) {
|
||||
case T:
|
||||
s.Add(t)
|
||||
default:
|
||||
// anything else must be skipped.
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
Open Source Initiative OSI - The MIT License (MIT):Licensing
|
||||
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
package mapset
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Want to test numbers, strings and some kind of struct.
|
||||
// That will be good enough.
|
||||
|
||||
func Test_Generic(t *testing.T) {
|
||||
a := newThreadUnsafeSetGeneric[int]()
|
||||
if a.Cardinality() != 0 {
|
||||
t.Error("should be empty")
|
||||
}
|
||||
|
||||
a.Add(5)
|
||||
if a.Cardinality() != 1 {
|
||||
t.Error("should have one element")
|
||||
}
|
||||
|
||||
a.Add(4)
|
||||
if a.Cardinality() != 2 {
|
||||
t.Error("should have 2 elements")
|
||||
}
|
||||
|
||||
s := a.ToSlice()
|
||||
fmt.Println(s)
|
||||
}
|
||||
|
||||
func Test_Generic_String(t *testing.T) {
|
||||
a := newThreadUnsafeSetGeneric[int]()
|
||||
a.Add(5)
|
||||
a.Add(4)
|
||||
|
||||
fmt.Println(a.String())
|
||||
}
|
||||
|
||||
func Test_Powerset(t *testing.T) {
|
||||
a := newThreadUnsafeSetGeneric[string]()
|
||||
a.Add("x")
|
||||
a.Add("y")
|
||||
a.Add("z")
|
||||
|
||||
ps := a.PowerSet()
|
||||
fmt.Println(ps)
|
||||
}
|
Loading…
Reference in New Issue