Trying to do functional programming with GO, the below code worked fine with me, but liked to share with the community for review/comments/feedback
package main
import (
"fmt"
"log"
"sort"
"time"
)
const (
layoutISO = "2006-01-02"
layoutUS = "January 2, 2006"
custom = "1/2/2006"
)
type Inventories []Inventory
type Inventory struct { //instead of: map[string]map[string]Pairs
Warehouse string
Item string
Batches Lots
}
type Lots []Lot
type Lot struct {
Date time.Time
Key string
Value float64
}
func main() {
fmt.Println("Hello, 世界")
date := "12/31/19" // "1999-12-31"
t, _ := time.Parse(custom, date)
var inventories = new(Inventories)
var inventory = new(Inventory) // Or = Inventory{} both are working //warehouse[item[batch, qty]]
inventory.Warehouse = "DMM"
inventory.Item = "Helmet"
inventory.Batches = append(inventory.Batches, Lot{t, "Jan", 10})
inventory.InsertBatch(Lot{time.Now(), "Jan", 30})
inventory.Batches.Insert(Lot{time.Now(), "Feb", 30})
fmt.Printf("\nBefore grouping: %v %T\n", inventory, inventory)
x := Inventory{
Warehouse: "DMM",
Item: "Gloves",
Batches: Lots{
Lot{mustTime(time.Parse(custom, "1/7/2020")), "Jan", 50},
Lot{mustTime(time.Parse(custom, "2/1/2020")), "Feb", 20},
Lot{mustTime(time.Parse(custom, "1/5/2020")), "Jan", 40},
Lot{mustTime(time.Parse(custom, "2/9/2020")), "Feb", 60},
},
}
fmt.Printf("\nBefore grouping: %v %T\n", x, x)
// Below can be used for grouping batches in each warehouse seperatly, this can be combined in the lines under
// inventory.Batches.Group()
// x.GroupBatches()
// fmt.Printf("\nAfter grouping: %v %T\n", inventory, inventory)
// fmt.Printf("\nAfter grouping: %v %T\n", x, x)
// Above can be replaced by below
inventories.Insert(*inventory)
inventories.Insert(x)
inventories.GroupBatches()
fmt.Printf("\nInventories after gouping batches: %v %T\n", inventories, inventories)
inventories.SortBatches()
fmt.Printf("\nInventories after sorting batches: %v %T\n", inventories, inventories)
}
func (i *Inventories) Insert(x Inventory) {
*i = append(*i, x)
}
func (i *Inventories) GroupBatches() {
inv := new(Inventories)
for _, el := range *i {
el.GroupBatches()
inv.Insert(el)
}
(*i).ReplaceBy(inv)
}
func (i *Inventories) SortBatches() {
inv := new(Inventories)
for _, el := range *i {
sort.Sort(Lots(el.Batches))
inv.Insert(el)
}
(*i).ReplaceBy(inv)
}
func (i *Inventories) ReplaceBy(x *Inventories) {
*i = *x
}
func (i *Inventory) InsertBatch(x Lot) {
(*i).Batches = append((*i).Batches, x)
}
func (i *Inventory) GroupBatches() {
(*i).Batches.Group()
}
func (p *Lots) Group() {
lots := new(Lots)
lots.FromMap(p.Map())
p.ReplaceBy(lots)
}
func (p *Lots) FromMap(m map[string]float64) {
for k, v := range m {
(*p).Insert(Lot{time.Now(), k, v})
}
}
// Below to enable sorting: sort.Sort(Lots(lots))
func (l Lots) Len() int { return len(l) }
func (l Lots) Less(i, j int) bool { return (l[i].Date).Before(l[j].Date) } // { return l[i].Key < l[j].Key }
func (l Lots) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
func (p *Lots) Insert(x Lot) {
*p = append(*p, x)
}
func (p *Lots) ReplaceBy(x *Lots) {
*p = *x
}
func (p *Lots) Map() map[string]float64 {
sum := make(map[string]float64)
for _, el := range *p {
sum[el.Key] = sum[el.Key] + el.Value
}
return sum
}
type Interface interface {
// Len is the number of elements in the collection.
Len() int
// Less reports whether the element with
// index i should sort before the element with index j.
Less(i, j int) bool
// Swap swaps the elements with indexes i and j.
Swap(i, j int)
}
func mustTime(t time.Time, err error) time.Time {
failOnError(err)
return t
}
func failOnError(err error) {
if err != nil {
log.Fatal("Error:", err)
panic(err)
}
}
The output is:
[Running] go run "d:\goplay\grouping.go"
Hello, 世界
Before grouping: &{DMM Helmet [{0001-01-01 00:00:00 +0000 UTC Jan 10} {2020-06-05 00:26:16.9165066 +0300 +03 m=+0.006981101 Jan 30} {2020-06-05 00:26:16.9165066 +0300 +03 m=+0.006981101 Feb 30}]} *main.Inventory
Before grouping: {DMM Gloves [{2020-01-07 00:00:00 +0000 UTC Jan 50} {2020-02-01 00:00:00 +0000 UTC Feb 20} {2020-01-05 00:00:00 +0000 UTC Jan 40} {2020-02-09 00:00:00 +0000 UTC Feb 60}]} main.Inventory
Inventories after gouping batches: &[{DMM Helmet [{2020-06-05 00:26:16.9175045 +0300 +03 m=+0.007979001 Jan 40} {2020-06-05 00:26:16.9175045 +0300 +03 m=+0.007979001 Feb 30}]} {DMM Gloves [{2020-06-05 00:26:16.9175045 +0300 +03 m=+0.007979001 Jan 90} {2020-06-05 00:26:16.9175045 +0300 +03 m=+0.007979001 Feb 80}]}] *main.Inventories
Inventories after sorting batches: &[{DMM Helmet [{2020-06-05 00:26:16.9175045 +0300 +03 m=+0.007979001 Jan 40} {2020-06-05 00:26:16.9175045 +0300 +03 m=+0.007979001 Feb 30}]} {DMM Gloves [{2020-06-05 00:26:16.9175045 +0300 +03 m=+0.007979001 Jan 90} {2020-06-05 00:26:16.9175045 +0300 +03 m=+0.007979001 Feb 80}]}] *main.Inventories
[Done] exited with code=0 in 3.624 seconds```