- Arrays: a value per
geom.Pointof a size, in one slice, with sides of any integer type. - Sets: immutable sorted sets of any
Compareelement, with union, intersection and difference.
The rules behind them are in the package documentation.
go get github.com/gravitton/containerimport "github.com/gravitton/container"An Array[T, S] holds one value for every index of a size in columns and rows. S is the
integer type of its sides and indices, taken from the size it is made with. An array is a handle,
as a slice is: a copy shares its values, and Clone gives storage of its own.
a := container.Arr[int](geom.Sz(4, 3)) // an Array[int, int], every value zero
small := container.Arr[uint8](geom.Sz[int16](320, 200)) // an Array[uint8, int16], indexed by geom.Point[int16]
a.Set(geom.Pt(2, 1), 7)
*a.Get(geom.Pt(2, 1)) += 1 // a pointer into the array
a.Contains(geom.Pt(4, 0)) // false, the check before Get and Set, which panic outside
a.Size() // 4x3; also Width, Height and Len
snapshot := a.Clone() // storage of its ownThe values are stored row by row, and every traversal follows that order: Keys walks the
indices, Data is the storage itself.
for index, value := range a.All() { // also Keys and Values
*value += index.X
}
values := a.Data() // the values row by row as a slice into the array, the fastest loop
for i := range values {
values[i] = min(values[i], 9)
}
data, err := json.Marshal(a) // {"w":4,"h":3,"d":[…]}, the values row by row
err = json.Unmarshal(data, &a) // and back; an error where the values do not fill the sizeA Set[E] holds any element with a Compare method, once each and in that order. It never
changes: every operation returns a set, so one is safe to copy and share.
a := container.SetOf(geom.Pt(1, 1), geom.Pt(2, 1), geom.Pt(1, 2), geom.Pt(2, 2))
from := container.SetFrom(points) // the same from a slice it takes as its own, without a copy
a.Contains(geom.Pt(2, 1)) // true, a binary search
a.Len() // 4; also IsEmpty
a.First() // (1,1), true; also Last
a.Index(geom.Pt(2, 1)) // 2, true, the index At reads it back fromEach operation walks both sets once and allocates its result once, or not at all where it equals one of them.
b := container.SetOf(geom.Pt(2, 2), geom.Pt(3, 2), geom.Pt(2, 3), geom.Pt(3, 3))
a.Union(b) // (1,1) (1,2) (2,1) (2,2) (2,3) (3,2) (3,3)
a.Intersection(b) // (2,2)
a.Difference(b) // (1,1) (1,2) (2,1)
a.SymmetricDifference(b) // (1,1) (1,2) (2,1) (2,3) (3,2) (3,3)
a.Intersects(b) // true, without building the intersection
a.Encloses(b) // false, whether a holds every element of b
a.Equal(b) // falseA set is walked and stored in its order:
for p := range a.All() { // also Backward
draw(p)
}
a.Elements() // a fresh slice; also AppendElements
json.Marshal(a) // [{"x":1,"y":1},…], null for the empty setFull reference: pkg.go.dev.
A container knows no layout: an array has no neighbors and a set no shape. Those belong to the package that gives the indices a meaning. A new container joins when a second package needs it, so there is no map, list, heap or queue until a game asks for one.
The MIT License (MIT). Please see License File for more information.