bag — counted collection (multiset)
github.com/go-composites/bag (Go package Bag, imported from the src/
sub-directory) is the org's multiset composite — a collection of items each
carrying a multiplicity (a count), so the same value can be held more than
once. It rounds out the collection family next to set (unique),
orderedset (insertion-ordered) and sortedset
(comparator-sorted), and shares the Each/ToArray grammar with
array. Items are arbitrary comparable values (a Bag is backed
by a Go map, exactly like a dictionary key). Membership tests
return a plain bool, fallible iteration returns a result, and
every method honours the Null-Object invariant (never nil).
API
import Bag "github.com/go-composites/bag/src"
type Interface interface {
Add(item interface{}) Interface
Remove(item interface{}) Interface
Count(item interface{}) int
Has(item interface{}) bool
Len() int
DistinctLen() int
IsEmpty() bool
Each(fn func(item interface{}, count int) Result.Interface) Result.Interface
ToArray() Array.Interface
DistinctArray() Array.Interface
Sum(other Interface) Interface
Union(other Interface) Interface
Intersection(other Interface) Interface
Difference(other Interface) Interface
Equal(other Interface) bool
IsNull() bool
}
func New(items ...interface{}) Interface
func Null() Interface
New(items...)builds aBagseeded with the given items, counting duplicates — soNew(1, 1, 2)holds1with a count of2and2with a count of1.Null()returns the Null-Object bag (see below).
| Member | Behaviour |
|---|---|
Add(item) |
Increments item's count by one and returns the receiver, so calls chain. |
Remove(item) |
Decrements item's count by one, dropping the item entirely when its count reaches zero (a no-op when absent), and returns the receiver, so calls chain. |
Count(item) |
Returns item's multiplicity, or 0 when absent. |
Has(item) |
Returns a plain bool reporting whether item is present (count greater than zero). |
Len() |
Returns the total size counting multiplicity (the sum of all counts). |
DistinctLen() |
Returns the number of distinct items, ignoring multiplicity. |
IsEmpty() |
Returns true when the bag has no items. |
Each(fn) |
Invokes fn per distinct item with that item and its count; short-circuits and returns the first Result whose HasError() is true, otherwise returns a fresh Result.New(). Order is unspecified (Go map order). |
ToArray() |
Materialises the bag into an array, repeating each item by its count, in unspecified order. |
DistinctArray() |
Materialises the distinct items into an array, each appearing once regardless of count, in unspecified order. |
Sum(other) |
Returns a new Bag whose count for each item is the sum of its counts in this bag and in other (multiset additive union). |
Union(other) |
Returns a new Bag whose count for each item is the maximum of its counts in this bag and in other (multiset union). |
Intersection(other) |
Returns a new Bag whose count for each item is the minimum of its counts in both bags (multiset intersection); items absent from either bag are omitted. |
Difference(other) |
Returns a new Bag whose count for each item is its count here minus its count in other, floored at zero (multiset difference); items reaching zero are omitted. |
Equal(other) |
Reports whether both bags contain exactly the same items with exactly the same counts. |
IsNull() |
Returns false for a real bag, true for the Null() one. |
Usage
a := Bag.New(1, 1, 2) // 1×2, 2×1
b := Bag.New(1, 2, 2, 3) // 1×1, 2×2, 3×1
a.Add(1) // 1×3, 2×1
fmt.Println(a.Has(2)) // true
fmt.Println(a.Count(1)) // 3
fmt.Println(a.Len()) // 4 (total with multiplicity)
fmt.Println(a.DistinctLen()) // 2 (distinct items)
fmt.Println(a.Sum(b).Count(2)) // 3 (1 + 2)
fmt.Println(a.Union(b).Count(2)) // 2 (max of 1 and 2)
fmt.Println(a.Intersection(b).Count(1)) // 1 (min of 3 and 1)
fmt.Println(a.Difference(b).Count(1)) // 2 (3 − 1)
The Null-Object variant
Bag.Null() honours the full Interface without ever being nil: mutating
methods (Add, Remove) are no-ops returning the receiver, every query is
empty/false/zero (Has is false, Count is 0, Len()/DistinctLen()
are 0, IsEmpty() is true), Each is a clean pass, the multiset
operations return the receiver, Equal(other) is other.IsEmpty(), and
IsNull() returns true.
Dependencies
bag depends on array and result (and transitively
on error and null).