Skip to content

Commit edae377

Browse files
authored
Add generic packages (#162)
* add generic packages * code review fixes * rename fallback to defaultValue * rename uniqueSlice to orderedSet * fix code review comments * fix partitioning alg
1 parent 027a72b commit edae377

11 files changed

+412
-22
lines changed

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
*.out
1313

1414
# Dependency directories (remove the comment below to include it)
15-
# vendor/
15+
vendor/
1616

1717
.idea/
1818
.vscode/

go.mod

+3-5
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ require (
1616
github.com/spf13/viper v1.8.1
1717
github.com/streadway/amqp v1.0.0
1818
github.com/stretchr/testify v1.7.0
19+
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91
1920
gotest.tools v2.2.0+incompatible
2021
)
2122

2223
require (
2324
github.com/kr/pretty v0.3.0 // indirect
24-
github.com/pierrec/lz4/v4 v4.1.14 // indirect
2525
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
2626
)
2727

@@ -40,11 +40,10 @@ require (
4040
github.com/gogap/env_json v0.0.0-20150503135429-86150085ddbe // indirect
4141
github.com/gogap/env_strings v0.0.1 // indirect
4242
github.com/golang/protobuf v1.5.2 // indirect
43-
github.com/google/go-cmp v0.5.7 // indirect
43+
github.com/google/go-cmp v0.5.8 // indirect
4444
github.com/hashicorp/hcl v1.0.0 // indirect
4545
github.com/hoisie/redis v0.0.0-20160730154456-b5c6e81454e0 // indirect
4646
github.com/json-iterator/go v1.1.12 // indirect
47-
github.com/klauspost/compress v1.14.4 // indirect
4847
github.com/leodido/go-urn v1.2.0 // indirect
4948
github.com/magiconair/properties v1.8.5 // indirect
5049
github.com/mattn/go-isatty v0.0.12 // indirect
@@ -60,7 +59,6 @@ require (
6059
github.com/prometheus/client_model v0.2.0 // indirect
6160
github.com/prometheus/common v0.32.1 // indirect
6261
github.com/prometheus/procfs v0.7.3 // indirect
63-
github.com/segmentio/kafka-go v0.4.31
6462
github.com/spf13/afero v1.6.0 // indirect
6563
github.com/spf13/cast v1.3.1 // indirect
6664
github.com/spf13/jwalterweatherman v1.1.0 // indirect
@@ -73,7 +71,7 @@ require (
7371
go.opentelemetry.io/otel/trace v0.19.0 // indirect
7472
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect
7573
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
76-
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
74+
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
7775
golang.org/x/text v0.3.7 // indirect
7876
google.golang.org/protobuf v1.26.0 // indirect
7977
gopkg.in/ini.v1 v1.62.0 // indirect

go.sum

+6-16
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,8 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
170170
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
171171
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
172172
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
173-
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
174-
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
173+
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
174+
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
175175
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
176176
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
177177
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
@@ -239,9 +239,6 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
239239
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
240240
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
241241
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
242-
github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
243-
github.com/klauspost/compress v1.14.4 h1:eijASRJcobkVtSt81Olfh7JX43osYLwy5krOJo6YEu4=
244-
github.com/klauspost/compress v1.14.4/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
245242
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
246243
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
247244
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
@@ -301,8 +298,6 @@ github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaR
301298
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
302299
github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ=
303300
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
304-
github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE=
305-
github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
306301
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
307302
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
308303
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -339,8 +334,6 @@ github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBO
339334
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
340335
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
341336
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
342-
github.com/segmentio/kafka-go v0.4.31 h1:+ImsrkJRju9j1D9U44rvRGRlpsI9GnwD8s9WTFagNLQ=
343-
github.com/segmentio/kafka-go v0.4.31/go.mod h1:m1lXeqJtIFYZayv0shM/tjrAFljvWLTprxBHd+3PnaU=
344337
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
345338
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
346339
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
@@ -376,10 +369,6 @@ github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69
376369
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
377370
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
378371
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
379-
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV0YCnDjqSL7/q/JyPhhJSPk=
380-
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
381-
github.com/xdg/stringprep v1.0.0 h1:d9X0esnoa3dFsV0FG35rAT0RIhYFlPq7MiP+DW89La0=
382-
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
383372
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
384373
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
385374
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -411,7 +400,6 @@ go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
411400
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
412401
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
413402
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
414-
golang.org/x/crypto v0.0.0-20190506204251-e1dfcc566284/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
415403
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
416404
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
417405
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -429,6 +417,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
429417
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
430418
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
431419
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
420+
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91 h1:tnebWN09GYg9OLPss1KXj8txwZc6X6uMr6VFdcGNbHw=
421+
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
432422
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
433423
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
434424
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -579,8 +569,9 @@ golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7w
579569
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
580570
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
581571
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
582-
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
583572
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
573+
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
574+
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
584575
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
585576
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
586577
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -650,7 +641,6 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
650641
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
651642
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
652643
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
653-
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
654644
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
655645
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
656646
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=

set/ordered.go

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package set
2+
3+
type OrderedSet[T comparable] struct {
4+
valuesSet map[T]struct{}
5+
values []T
6+
}
7+
8+
func NewOrderedSet[T comparable]() *OrderedSet[T] {
9+
return &OrderedSet[T]{
10+
valuesSet: make(map[T]struct{}),
11+
values: make([]T, 0),
12+
}
13+
}
14+
15+
func (u *OrderedSet[T]) Add(val T) {
16+
if _, exists := u.valuesSet[val]; !exists {
17+
u.valuesSet[val] = struct{}{}
18+
u.values = append(u.values, val)
19+
}
20+
}
21+
22+
func (u *OrderedSet[T]) Contains(val T) bool {
23+
_, contains := u.valuesSet[val]
24+
return contains
25+
}
26+
27+
func (u *OrderedSet[T]) Values() []T {
28+
return u.values
29+
}

set/ordered_test.go

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package set
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
9+
func TestContains(t *testing.T) {
10+
t.Run("int", func(t *testing.T) {
11+
u := NewOrderedSet[int]()
12+
u.Add(1)
13+
u.Add(5)
14+
u.Add(5)
15+
u.Add(8)
16+
assert.Equal(t, []int{1, 5, 8}, u.Values())
17+
})
18+
19+
t.Run("str", func(t *testing.T) {
20+
u := NewOrderedSet[string]()
21+
u.Add("foo")
22+
u.Add("bar")
23+
u.Add("baz")
24+
u.Add("foo")
25+
assert.Equal(t, []string{"foo", "bar", "baz"}, u.Values())
26+
})
27+
}

set/set.go

+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package set
2+
3+
import (
4+
"encoding/json"
5+
)
6+
7+
type Set[T comparable] struct {
8+
values map[T]struct{}
9+
}
10+
11+
func New[T comparable]() *Set[T] {
12+
return &Set[T]{
13+
values: make(map[T]struct{}),
14+
}
15+
}
16+
17+
func NewFromValues[T comparable](values ...T) *Set[T] {
18+
s := New[T]()
19+
s.Add(values...)
20+
return s
21+
}
22+
23+
func (s *Set[T]) Add(values ...T) {
24+
for _, val := range values {
25+
s.values[val] = struct{}{}
26+
}
27+
}
28+
29+
func (s *Set[T]) Clear() {
30+
s.values = make(map[T]struct{})
31+
}
32+
33+
func (s *Set[T]) Remove(val T) {
34+
delete(s.values, val)
35+
}
36+
37+
func (s *Set[T]) Contains(val T) bool {
38+
_, contains := s.values[val]
39+
return contains
40+
}
41+
42+
func (s *Set[T]) ContainsAny(values ...T) bool {
43+
for _, val := range values {
44+
if s.Contains(val) {
45+
return true
46+
}
47+
}
48+
49+
return false
50+
}
51+
52+
func (s *Set[T]) ContainsAll(values ...T) bool {
53+
for _, val := range values {
54+
if !s.Contains(val) {
55+
return false
56+
}
57+
}
58+
59+
return true
60+
}
61+
62+
func (s *Set[T]) Extend(s2 *Set[T]) {
63+
for v := range s2.Values() {
64+
s.Add(v)
65+
}
66+
}
67+
68+
func (s *Set[T]) Size() int {
69+
return len(s.values)
70+
}
71+
72+
func (s *Set[T]) Values() map[T]struct{} {
73+
return s.values
74+
}
75+
76+
func (s *Set[T]) ToSlice() []T {
77+
sl := make([]T, 0, len(s.values))
78+
79+
for v := range s.values {
80+
sl = append(sl, v)
81+
}
82+
return sl
83+
}
84+
85+
func (s *Set[T]) MarshalJSON() ([]byte, error) {
86+
return json.Marshal(s.ToSlice())
87+
}
88+
89+
func (s *Set[T]) UnmarshalJSON(data []byte) error {
90+
values := make([]T, 0)
91+
92+
err := json.Unmarshal(data, &values)
93+
if err != nil {
94+
return err
95+
}
96+
97+
s.Clear()
98+
for _, v := range values {
99+
s.Add(v)
100+
}
101+
102+
return nil
103+
}

set/set_test.go

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package set
2+
3+
import (
4+
"encoding/json"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestSetFromValues(t *testing.T) {
11+
s := NewFromValues("foo", "bar")
12+
assert.Equal(t, 2, s.Size())
13+
assert.True(t, s.Contains("foo"))
14+
assert.True(t, s.Contains("bar"))
15+
assert.False(t, s.Contains("baz"))
16+
}
17+
18+
func TestSet(t *testing.T) {
19+
s := New[string]()
20+
assert.Empty(t, s.ToSlice())
21+
22+
s.Add("foo")
23+
s.Add("bar")
24+
assert.Equal(t, 2, s.Size())
25+
26+
s.Add("bar", "baz")
27+
assert.True(t, s.Contains("foo"))
28+
assert.True(t, s.Contains("bar"))
29+
assert.True(t, s.Contains("baz"))
30+
assert.Equal(t, 3, s.Size())
31+
32+
s.Remove("baz")
33+
assert.Equal(t, 2, s.Size())
34+
35+
s.Remove("foo")
36+
assert.Equal(t, 1, s.Size())
37+
38+
assert.False(t, s.Contains("foo"))
39+
assert.True(t, s.Contains("bar"))
40+
assert.Equal(t, []string{"bar"}, s.ToSlice())
41+
42+
s.Clear()
43+
assert.False(t, s.Contains("bar"))
44+
assert.Empty(t, s.ToSlice())
45+
assert.Equal(t, 0, s.Size())
46+
47+
t.Run("unmarshal", func(t *testing.T) {
48+
mySet := New[string]()
49+
mySet.Add("whatever")
50+
51+
values := []string{"a", "b", "foo", "c", "b"}
52+
jsb, _ := json.Marshal(values)
53+
assert.NoError(t, json.Unmarshal(jsb, &mySet))
54+
assert.Equal(t, 4, mySet.Size())
55+
for _, v := range values {
56+
assert.True(t, mySet.Contains(v))
57+
}
58+
})
59+
60+
}

slice/partition.go

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package slice
2+
3+
// Partition creates partitions of a standard maximum size.
4+
func Partition[T any](s []T, partitionSize int) [][]T {
5+
if len(s) == 0 || partitionSize <= 0 {
6+
return [][]T{}
7+
}
8+
9+
partitions := make([][]T, 0, (len(s)+partitionSize-1)/partitionSize)
10+
11+
for {
12+
left := len(partitions) * partitionSize
13+
if left >= len(s) {
14+
break
15+
}
16+
17+
right := Min(left+partitionSize, len(s))
18+
19+
part := s[left:right]
20+
partition := make([]T, len(part))
21+
copy(partition, part)
22+
23+
partitions = append(partitions, partition)
24+
}
25+
26+
return partitions
27+
}

0 commit comments

Comments
 (0)