diff --git a/cmd/generate/gen_x_seq.go.tmpl b/cmd/generate/gen_x_seq.go.tmpl index fc55be5..90b0190 100644 --- a/cmd/generate/gen_x_seq.go.tmpl +++ b/cmd/generate/gen_x_seq.go.tmpl @@ -7,37 +7,46 @@ import ( "time" ) +// {{.Name}} is a time point with {{.Type}} value inside type {{.Name}} struct { Time time.Time Value {{.Type}} } +// IsZero return if time and value are both zero func (v {{.Name}}) IsZero() bool { return v.Value == 0 && v.Time.IsZero() } +// IsZero return if time and value are both equal func (v {{.Name}}) Equal(n {{.Name}}) bool { return v.Value == n.Value && v.Time.Equal(n.Time) } +// {{.Name}}s is a alias of {{.Name}} slice type {{.Name}}s []{{.Name}} +// Len implements Interface.Len() func (s {{.Name}}s) Len() int { return len(s) } +// Swap implements Interface.Swap() func (s {{.Name}}s) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +// Time implements Interface.Time() func (s {{.Name}}s) Time(i int) time.Time { return s[i].Time } +// Slice implements Interface.Slice() func (s {{.Name}}s) Slice(i, j int) Interface { return s[i:j] } +// {{.Name}}Seq is a wrapper with useful methods of {{.Name}} slice type {{.Name}}Seq struct { slice {{.Name}}s @@ -47,12 +56,14 @@ type {{.Name}}Seq struct { valueSlice []int } +// New{{.Name}}Seq return *{{.Name}}Seq with copied slice inside func New{{.Name}}Seq(slice {{.Name}}s) *{{.Name}}Seq { temp := make({{.Name}}s, len(slice)) copy(temp, slice) return Wrap{{.Name}}Seq(temp) } +// Wrap{{.Name}}Seq return *{{.Name}}Seq with origin slice inside func Wrap{{.Name}}Seq(slice {{.Name}}s) *{{.Name}}Seq { if !IsSorted(slice) { Sort(slice) @@ -91,16 +102,19 @@ func (s *{{.Name}}Seq) resetIndex() { s.indexOnce = sync.Once{} } +// {{.Name}}s return a replica of inside slice func (s *{{.Name}}Seq) {{.Name}}s() {{.Name}}s { slice := make({{.Name}}s, len(s.slice)) copy(slice, s.slice) return slice } +// Len return length of inside slice func (s *{{.Name}}Seq) Len() int { return len(s.slice) } +// Index return element of inside slice, return zero if index is out of range func (s *{{.Name}}Seq) Index(i int) {{.Name}} { if i < 0 || i >= len(s.slice) { return {{.Name}}{} @@ -108,6 +122,7 @@ func (s *{{.Name}}Seq) Index(i int) {{.Name}} { return s.slice[i] } +// Time return the first element with time t, return zero if not found func (s *{{.Name}}Seq) Time(t time.Time) {{.Name}} { got := s.MTime(t) if len(got) == 0 { @@ -116,6 +131,7 @@ func (s *{{.Name}}Seq) Time(t time.Time) {{.Name}} { return got[0] } +// MTime return all elements with time t, return nil if not found func (s *{{.Name}}Seq) MTime(t time.Time) {{.Name}}s { s.buildIndex() index := s.timeIndex[newTimeKey(t)] @@ -129,6 +145,7 @@ func (s *{{.Name}}Seq) MTime(t time.Time) {{.Name}}s { return ret } +// Value return the first element with value v, return zero if not found func (s *{{.Name}}Seq) Value(v {{.Type}}) {{.Name}} { got := s.MValue(v) if len(got) == 0 { @@ -137,6 +154,7 @@ func (s *{{.Name}}Seq) Value(v {{.Type}}) {{.Name}} { return got[0] } +// MValue return all elements with value v, return nil if not found func (s *{{.Name}}Seq) MValue(v {{.Type}}) {{.Name}}s { s.buildIndex() index := s.valueIndex[v] @@ -150,7 +168,8 @@ func (s *{{.Name}}Seq) MValue(v {{.Type}}) {{.Name}}s { return ret } -func (s *{{.Name}}Seq) Visit(fn func(i int, v {{.Name}}) (stop bool)) { +// Traverse call fn for every element one by one, break if fn return true +func (s *{{.Name}}Seq) Traverse(fn func(i int, v {{.Name}}) (stop bool)) { for i, v := range s.slice { if fn != nil && fn(i, v) { break @@ -158,6 +177,7 @@ func (s *{{.Name}}Seq) Visit(fn func(i int, v {{.Name}}) (stop bool)) { } } +// Sum return sum of all values func (s *{{.Name}}Seq) Sum() {{.Type}} { var ret {{.Type}} for _, v := range s.slice { @@ -166,10 +186,12 @@ func (s *{{.Name}}Seq) Sum() {{.Type}} { return ret } +// Count return count of elements, same as Len func (s *{{.Name}}Seq) Count() int { return s.Len() } +// Max return the element with max value, return zero if empty func (s *{{.Name}}Seq) Max() {{.Name}} { var max {{.Name}} found := false @@ -184,6 +206,7 @@ func (s *{{.Name}}Seq) Max() {{.Name}} { return max } +// Max return the element with min value, return zero if empty func (s *{{.Name}}Seq) Min() {{.Name}} { var min {{.Name}} found := false @@ -198,6 +221,7 @@ func (s *{{.Name}}Seq) Min() {{.Name}} { return min } +// First return the first element, return zero if empty func (s *{{.Name}}Seq) First() {{.Name}} { if len(s.slice) == 0 { return {{.Name}}{} @@ -205,6 +229,7 @@ func (s *{{.Name}}Seq) First() {{.Name}} { return s.slice[0] } +// Last return the last element, return zero if empty func (s *{{.Name}}Seq) Last() {{.Name}} { if len(s.slice) == 0 { return {{.Name}}{} @@ -212,6 +237,8 @@ func (s *{{.Name}}Seq) Last() {{.Name}} { return s.slice[len(s.slice)-1] } +// Percentile return the element matched with percentile pct, return zero if empty, +// the pct's valid range is be [0, 1], it will be treated as 1 if greater than 1, as 0 if smaller than 0 func (s *{{.Name}}Seq) Percentile(pct float64) {{.Name}} { s.buildIndex() if len(s.slice) == 0 { @@ -230,11 +257,13 @@ func (s *{{.Name}}Seq) Percentile(pct float64) {{.Name}} { return s.slice[s.valueSlice[i]] } +// Range return a sub *{{.Name}}Seq with specified interval func (s *{{.Name}}Seq) Range(interval Interval) *{{.Name}}Seq { slice := Range(s.slice, interval).({{.Name}}s) return new{{.Name}}Seq(slice) } +// Merge merge slices to inside slice according to the specified rule func (s *{{.Name}}Seq) Merge(fn func(t time.Time, v1, v2 *{{.Type}}) *{{.Type}}, slices ...{{.Name}}s) error { if fn == nil { return errors.New("nil fn") @@ -302,6 +331,7 @@ func (s *{{.Name}}Seq) Merge(fn func(t time.Time, v1, v2 *{{.Type}}) *{{.Type}}, return nil } +// Aggregate aggregate inside slice according to the specified rule func (s *{{.Name}}Seq) Aggregate(fn func(t time.Time, slice {{.Name}}s) *{{.Type}}, duration time.Duration, interval Interval) error { if fn == nil { return errors.New("nil fn") @@ -363,6 +393,7 @@ func (s *{{.Name}}Seq) Aggregate(fn func(t time.Time, slice {{.Name}}s) *{{.Type return nil } +// Trim remove the elements which make fn return true func (s *{{.Name}}Seq) Trim(fn func(i int, v {{.Name}}) bool) error { if fn == nil { return errors.New("nil fn") @@ -385,6 +416,7 @@ func (s *{{.Name}}Seq) Trim(fn func(i int, v {{.Name}}) bool) error { return nil } +// Clone return a new *{{.Name}}Seq with copied slice inside func (s *{{.Name}}Seq) Clone() *{{.Name}}Seq { if s == nil { return nil diff --git a/cmd/generate/gen_x_seq_test.go.tmpl b/cmd/generate/gen_x_seq_test.go.tmpl index e31b2f2..2502d95 100644 --- a/cmd/generate/gen_x_seq_test.go.tmpl +++ b/cmd/generate/gen_x_seq_test.go.tmpl @@ -333,7 +333,7 @@ func Test{{.Name}}Seq_MValue(t *testing.T) { } } -func Test{{.Name}}Seq_Visit(t *testing.T) { +func Test{{.Name}}Seq_Traverse(t *testing.T) { data := Random{{.Name}}s(100) type args struct { @@ -363,7 +363,7 @@ func Test{{.Name}}Seq_Visit(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { s := New{{.Name}}Seq(data) - s.Visit(tt.args.fn) + s.Traverse(tt.args.fn) }) } } diff --git a/gen_float64_seq.go b/gen_float64_seq.go index 02220a5..5b48721 100644 --- a/gen_float64_seq.go +++ b/gen_float64_seq.go @@ -9,37 +9,46 @@ import ( "time" ) +// Float64 is a time point with float64 value inside type Float64 struct { Time time.Time Value float64 } +// IsZero return if time and value are both zero func (v Float64) IsZero() bool { return v.Value == 0 && v.Time.IsZero() } +// IsZero return if time and value are both equal func (v Float64) Equal(n Float64) bool { return v.Value == n.Value && v.Time.Equal(n.Time) } +// Float64s is a alias of Float64 slice type Float64s []Float64 +// Len implements Interface.Len() func (s Float64s) Len() int { return len(s) } +// Swap implements Interface.Swap() func (s Float64s) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +// Time implements Interface.Time() func (s Float64s) Time(i int) time.Time { return s[i].Time } +// Slice implements Interface.Slice() func (s Float64s) Slice(i, j int) Interface { return s[i:j] } +// Float64Seq is a wrapper with useful methods of Float64 slice type Float64Seq struct { slice Float64s @@ -49,12 +58,14 @@ type Float64Seq struct { valueSlice []int } +// NewFloat64Seq return *Float64Seq with copied slice inside func NewFloat64Seq(slice Float64s) *Float64Seq { temp := make(Float64s, len(slice)) copy(temp, slice) return WrapFloat64Seq(temp) } +// WrapFloat64Seq return *Float64Seq with origin slice inside func WrapFloat64Seq(slice Float64s) *Float64Seq { if !IsSorted(slice) { Sort(slice) @@ -93,16 +104,19 @@ func (s *Float64Seq) resetIndex() { s.indexOnce = sync.Once{} } +// Float64s return a replica of inside slice func (s *Float64Seq) Float64s() Float64s { slice := make(Float64s, len(s.slice)) copy(slice, s.slice) return slice } +// Len return length of inside slice func (s *Float64Seq) Len() int { return len(s.slice) } +// Index return element of inside slice, return zero if index is out of range func (s *Float64Seq) Index(i int) Float64 { if i < 0 || i >= len(s.slice) { return Float64{} @@ -110,6 +124,7 @@ func (s *Float64Seq) Index(i int) Float64 { return s.slice[i] } +// Time return the first element with time t, return zero if not found func (s *Float64Seq) Time(t time.Time) Float64 { got := s.MTime(t) if len(got) == 0 { @@ -118,6 +133,7 @@ func (s *Float64Seq) Time(t time.Time) Float64 { return got[0] } +// MTime return all elements with time t, return nil if not found func (s *Float64Seq) MTime(t time.Time) Float64s { s.buildIndex() index := s.timeIndex[newTimeKey(t)] @@ -131,6 +147,7 @@ func (s *Float64Seq) MTime(t time.Time) Float64s { return ret } +// Value return the first element with value v, return zero if not found func (s *Float64Seq) Value(v float64) Float64 { got := s.MValue(v) if len(got) == 0 { @@ -139,6 +156,7 @@ func (s *Float64Seq) Value(v float64) Float64 { return got[0] } +// MValue return all elements with value v, return nil if not found func (s *Float64Seq) MValue(v float64) Float64s { s.buildIndex() index := s.valueIndex[v] @@ -152,7 +170,8 @@ func (s *Float64Seq) MValue(v float64) Float64s { return ret } -func (s *Float64Seq) Visit(fn func(i int, v Float64) (stop bool)) { +// Traverse call fn for every element one by one, break if fn return true +func (s *Float64Seq) Traverse(fn func(i int, v Float64) (stop bool)) { for i, v := range s.slice { if fn != nil && fn(i, v) { break @@ -160,6 +179,7 @@ func (s *Float64Seq) Visit(fn func(i int, v Float64) (stop bool)) { } } +// Sum return sum of all values func (s *Float64Seq) Sum() float64 { var ret float64 for _, v := range s.slice { @@ -168,10 +188,12 @@ func (s *Float64Seq) Sum() float64 { return ret } +// Count return count of elements, same as Len func (s *Float64Seq) Count() int { return s.Len() } +// Max return the element with max value, return zero if empty func (s *Float64Seq) Max() Float64 { var max Float64 found := false @@ -186,6 +208,7 @@ func (s *Float64Seq) Max() Float64 { return max } +// Max return the element with min value, return zero if empty func (s *Float64Seq) Min() Float64 { var min Float64 found := false @@ -200,6 +223,7 @@ func (s *Float64Seq) Min() Float64 { return min } +// First return the first element, return zero if empty func (s *Float64Seq) First() Float64 { if len(s.slice) == 0 { return Float64{} @@ -207,6 +231,7 @@ func (s *Float64Seq) First() Float64 { return s.slice[0] } +// Last return the last element, return zero if empty func (s *Float64Seq) Last() Float64 { if len(s.slice) == 0 { return Float64{} @@ -214,6 +239,8 @@ func (s *Float64Seq) Last() Float64 { return s.slice[len(s.slice)-1] } +// Percentile return the element matched with percentile pct, return zero if empty, +// the pct's valid range is be [0, 1], it will be treated as 1 if greater than 1, as 0 if smaller than 0 func (s *Float64Seq) Percentile(pct float64) Float64 { s.buildIndex() if len(s.slice) == 0 { @@ -232,11 +259,13 @@ func (s *Float64Seq) Percentile(pct float64) Float64 { return s.slice[s.valueSlice[i]] } +// Range return a sub *Float64Seq with specified interval func (s *Float64Seq) Range(interval Interval) *Float64Seq { slice := Range(s.slice, interval).(Float64s) return newFloat64Seq(slice) } +// Merge merge slices to inside slice according to the specified rule func (s *Float64Seq) Merge(fn func(t time.Time, v1, v2 *float64) *float64, slices ...Float64s) error { if fn == nil { return errors.New("nil fn") @@ -304,6 +333,7 @@ func (s *Float64Seq) Merge(fn func(t time.Time, v1, v2 *float64) *float64, slice return nil } +// Aggregate aggregate inside slice according to the specified rule func (s *Float64Seq) Aggregate(fn func(t time.Time, slice Float64s) *float64, duration time.Duration, interval Interval) error { if fn == nil { return errors.New("nil fn") @@ -365,6 +395,7 @@ func (s *Float64Seq) Aggregate(fn func(t time.Time, slice Float64s) *float64, du return nil } +// Trim remove the elements which make fn return true func (s *Float64Seq) Trim(fn func(i int, v Float64) bool) error { if fn == nil { return errors.New("nil fn") @@ -387,6 +418,7 @@ func (s *Float64Seq) Trim(fn func(i int, v Float64) bool) error { return nil } +// Clone return a new *Float64Seq with copied slice inside func (s *Float64Seq) Clone() *Float64Seq { if s == nil { return nil diff --git a/gen_float64_seq_test.go b/gen_float64_seq_test.go index 8d5658c..976fad2 100644 --- a/gen_float64_seq_test.go +++ b/gen_float64_seq_test.go @@ -335,7 +335,7 @@ func TestFloat64Seq_MValue(t *testing.T) { } } -func TestFloat64Seq_Visit(t *testing.T) { +func TestFloat64Seq_Traverse(t *testing.T) { data := RandomFloat64s(100) type args struct { @@ -365,7 +365,7 @@ func TestFloat64Seq_Visit(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { s := NewFloat64Seq(data) - s.Visit(tt.args.fn) + s.Traverse(tt.args.fn) }) } } diff --git a/gen_int64_seq.go b/gen_int64_seq.go index 000827a..414dbf6 100644 --- a/gen_int64_seq.go +++ b/gen_int64_seq.go @@ -9,37 +9,46 @@ import ( "time" ) +// Int64 is a time point with int64 value inside type Int64 struct { Time time.Time Value int64 } +// IsZero return if time and value are both zero func (v Int64) IsZero() bool { return v.Value == 0 && v.Time.IsZero() } +// IsZero return if time and value are both equal func (v Int64) Equal(n Int64) bool { return v.Value == n.Value && v.Time.Equal(n.Time) } +// Int64s is a alias of Int64 slice type Int64s []Int64 +// Len implements Interface.Len() func (s Int64s) Len() int { return len(s) } +// Swap implements Interface.Swap() func (s Int64s) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +// Time implements Interface.Time() func (s Int64s) Time(i int) time.Time { return s[i].Time } +// Slice implements Interface.Slice() func (s Int64s) Slice(i, j int) Interface { return s[i:j] } +// Int64Seq is a wrapper with useful methods of Int64 slice type Int64Seq struct { slice Int64s @@ -49,12 +58,14 @@ type Int64Seq struct { valueSlice []int } +// NewInt64Seq return *Int64Seq with copied slice inside func NewInt64Seq(slice Int64s) *Int64Seq { temp := make(Int64s, len(slice)) copy(temp, slice) return WrapInt64Seq(temp) } +// WrapInt64Seq return *Int64Seq with origin slice inside func WrapInt64Seq(slice Int64s) *Int64Seq { if !IsSorted(slice) { Sort(slice) @@ -93,16 +104,19 @@ func (s *Int64Seq) resetIndex() { s.indexOnce = sync.Once{} } +// Int64s return a replica of inside slice func (s *Int64Seq) Int64s() Int64s { slice := make(Int64s, len(s.slice)) copy(slice, s.slice) return slice } +// Len return length of inside slice func (s *Int64Seq) Len() int { return len(s.slice) } +// Index return element of inside slice, return zero if index is out of range func (s *Int64Seq) Index(i int) Int64 { if i < 0 || i >= len(s.slice) { return Int64{} @@ -110,6 +124,7 @@ func (s *Int64Seq) Index(i int) Int64 { return s.slice[i] } +// Time return the first element with time t, return zero if not found func (s *Int64Seq) Time(t time.Time) Int64 { got := s.MTime(t) if len(got) == 0 { @@ -118,6 +133,7 @@ func (s *Int64Seq) Time(t time.Time) Int64 { return got[0] } +// MTime return all elements with time t, return nil if not found func (s *Int64Seq) MTime(t time.Time) Int64s { s.buildIndex() index := s.timeIndex[newTimeKey(t)] @@ -131,6 +147,7 @@ func (s *Int64Seq) MTime(t time.Time) Int64s { return ret } +// Value return the first element with value v, return zero if not found func (s *Int64Seq) Value(v int64) Int64 { got := s.MValue(v) if len(got) == 0 { @@ -139,6 +156,7 @@ func (s *Int64Seq) Value(v int64) Int64 { return got[0] } +// MValue return all elements with value v, return nil if not found func (s *Int64Seq) MValue(v int64) Int64s { s.buildIndex() index := s.valueIndex[v] @@ -152,7 +170,8 @@ func (s *Int64Seq) MValue(v int64) Int64s { return ret } -func (s *Int64Seq) Visit(fn func(i int, v Int64) (stop bool)) { +// Traverse call fn for every element one by one, break if fn return true +func (s *Int64Seq) Traverse(fn func(i int, v Int64) (stop bool)) { for i, v := range s.slice { if fn != nil && fn(i, v) { break @@ -160,6 +179,7 @@ func (s *Int64Seq) Visit(fn func(i int, v Int64) (stop bool)) { } } +// Sum return sum of all values func (s *Int64Seq) Sum() int64 { var ret int64 for _, v := range s.slice { @@ -168,10 +188,12 @@ func (s *Int64Seq) Sum() int64 { return ret } +// Count return count of elements, same as Len func (s *Int64Seq) Count() int { return s.Len() } +// Max return the element with max value, return zero if empty func (s *Int64Seq) Max() Int64 { var max Int64 found := false @@ -186,6 +208,7 @@ func (s *Int64Seq) Max() Int64 { return max } +// Max return the element with min value, return zero if empty func (s *Int64Seq) Min() Int64 { var min Int64 found := false @@ -200,6 +223,7 @@ func (s *Int64Seq) Min() Int64 { return min } +// First return the first element, return zero if empty func (s *Int64Seq) First() Int64 { if len(s.slice) == 0 { return Int64{} @@ -207,6 +231,7 @@ func (s *Int64Seq) First() Int64 { return s.slice[0] } +// Last return the last element, return zero if empty func (s *Int64Seq) Last() Int64 { if len(s.slice) == 0 { return Int64{} @@ -214,6 +239,8 @@ func (s *Int64Seq) Last() Int64 { return s.slice[len(s.slice)-1] } +// Percentile return the element matched with percentile pct, return zero if empty, +// the pct's valid range is be [0, 1], it will be treated as 1 if greater than 1, as 0 if smaller than 0 func (s *Int64Seq) Percentile(pct float64) Int64 { s.buildIndex() if len(s.slice) == 0 { @@ -232,11 +259,13 @@ func (s *Int64Seq) Percentile(pct float64) Int64 { return s.slice[s.valueSlice[i]] } +// Range return a sub *Int64Seq with specified interval func (s *Int64Seq) Range(interval Interval) *Int64Seq { slice := Range(s.slice, interval).(Int64s) return newInt64Seq(slice) } +// Merge merge slices to inside slice according to the specified rule func (s *Int64Seq) Merge(fn func(t time.Time, v1, v2 *int64) *int64, slices ...Int64s) error { if fn == nil { return errors.New("nil fn") @@ -304,6 +333,7 @@ func (s *Int64Seq) Merge(fn func(t time.Time, v1, v2 *int64) *int64, slices ...I return nil } +// Aggregate aggregate inside slice according to the specified rule func (s *Int64Seq) Aggregate(fn func(t time.Time, slice Int64s) *int64, duration time.Duration, interval Interval) error { if fn == nil { return errors.New("nil fn") @@ -365,6 +395,7 @@ func (s *Int64Seq) Aggregate(fn func(t time.Time, slice Int64s) *int64, duration return nil } +// Trim remove the elements which make fn return true func (s *Int64Seq) Trim(fn func(i int, v Int64) bool) error { if fn == nil { return errors.New("nil fn") @@ -387,6 +418,7 @@ func (s *Int64Seq) Trim(fn func(i int, v Int64) bool) error { return nil } +// Clone return a new *Int64Seq with copied slice inside func (s *Int64Seq) Clone() *Int64Seq { if s == nil { return nil diff --git a/gen_int64_seq_test.go b/gen_int64_seq_test.go index 48358b5..6f8952c 100644 --- a/gen_int64_seq_test.go +++ b/gen_int64_seq_test.go @@ -335,7 +335,7 @@ func TestInt64Seq_MValue(t *testing.T) { } } -func TestInt64Seq_Visit(t *testing.T) { +func TestInt64Seq_Traverse(t *testing.T) { data := RandomInt64s(100) type args struct { @@ -365,7 +365,7 @@ func TestInt64Seq_Visit(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { s := NewInt64Seq(data) - s.Visit(tt.args.fn) + s.Traverse(tt.args.fn) }) } } diff --git a/gen_int_seq.go b/gen_int_seq.go index e56c2f2..31a53c6 100644 --- a/gen_int_seq.go +++ b/gen_int_seq.go @@ -9,37 +9,46 @@ import ( "time" ) +// Int is a time point with int value inside type Int struct { Time time.Time Value int } +// IsZero return if time and value are both zero func (v Int) IsZero() bool { return v.Value == 0 && v.Time.IsZero() } +// IsZero return if time and value are both equal func (v Int) Equal(n Int) bool { return v.Value == n.Value && v.Time.Equal(n.Time) } +// Ints is a alias of Int slice type Ints []Int +// Len implements Interface.Len() func (s Ints) Len() int { return len(s) } +// Swap implements Interface.Swap() func (s Ints) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +// Time implements Interface.Time() func (s Ints) Time(i int) time.Time { return s[i].Time } +// Slice implements Interface.Slice() func (s Ints) Slice(i, j int) Interface { return s[i:j] } +// IntSeq is a wrapper with useful methods of Int slice type IntSeq struct { slice Ints @@ -49,12 +58,14 @@ type IntSeq struct { valueSlice []int } +// NewIntSeq return *IntSeq with copied slice inside func NewIntSeq(slice Ints) *IntSeq { temp := make(Ints, len(slice)) copy(temp, slice) return WrapIntSeq(temp) } +// WrapIntSeq return *IntSeq with origin slice inside func WrapIntSeq(slice Ints) *IntSeq { if !IsSorted(slice) { Sort(slice) @@ -93,16 +104,19 @@ func (s *IntSeq) resetIndex() { s.indexOnce = sync.Once{} } +// Ints return a replica of inside slice func (s *IntSeq) Ints() Ints { slice := make(Ints, len(s.slice)) copy(slice, s.slice) return slice } +// Len return length of inside slice func (s *IntSeq) Len() int { return len(s.slice) } +// Index return element of inside slice, return zero if index is out of range func (s *IntSeq) Index(i int) Int { if i < 0 || i >= len(s.slice) { return Int{} @@ -110,6 +124,7 @@ func (s *IntSeq) Index(i int) Int { return s.slice[i] } +// Time return the first element with time t, return zero if not found func (s *IntSeq) Time(t time.Time) Int { got := s.MTime(t) if len(got) == 0 { @@ -118,6 +133,7 @@ func (s *IntSeq) Time(t time.Time) Int { return got[0] } +// MTime return all elements with time t, return nil if not found func (s *IntSeq) MTime(t time.Time) Ints { s.buildIndex() index := s.timeIndex[newTimeKey(t)] @@ -131,6 +147,7 @@ func (s *IntSeq) MTime(t time.Time) Ints { return ret } +// Value return the first element with value v, return zero if not found func (s *IntSeq) Value(v int) Int { got := s.MValue(v) if len(got) == 0 { @@ -139,6 +156,7 @@ func (s *IntSeq) Value(v int) Int { return got[0] } +// MValue return all elements with value v, return nil if not found func (s *IntSeq) MValue(v int) Ints { s.buildIndex() index := s.valueIndex[v] @@ -152,7 +170,8 @@ func (s *IntSeq) MValue(v int) Ints { return ret } -func (s *IntSeq) Visit(fn func(i int, v Int) (stop bool)) { +// Traverse call fn for every element one by one, break if fn return true +func (s *IntSeq) Traverse(fn func(i int, v Int) (stop bool)) { for i, v := range s.slice { if fn != nil && fn(i, v) { break @@ -160,6 +179,7 @@ func (s *IntSeq) Visit(fn func(i int, v Int) (stop bool)) { } } +// Sum return sum of all values func (s *IntSeq) Sum() int { var ret int for _, v := range s.slice { @@ -168,10 +188,12 @@ func (s *IntSeq) Sum() int { return ret } +// Count return count of elements, same as Len func (s *IntSeq) Count() int { return s.Len() } +// Max return the element with max value, return zero if empty func (s *IntSeq) Max() Int { var max Int found := false @@ -186,6 +208,7 @@ func (s *IntSeq) Max() Int { return max } +// Max return the element with min value, return zero if empty func (s *IntSeq) Min() Int { var min Int found := false @@ -200,6 +223,7 @@ func (s *IntSeq) Min() Int { return min } +// First return the first element, return zero if empty func (s *IntSeq) First() Int { if len(s.slice) == 0 { return Int{} @@ -207,6 +231,7 @@ func (s *IntSeq) First() Int { return s.slice[0] } +// Last return the last element, return zero if empty func (s *IntSeq) Last() Int { if len(s.slice) == 0 { return Int{} @@ -214,6 +239,8 @@ func (s *IntSeq) Last() Int { return s.slice[len(s.slice)-1] } +// Percentile return the element matched with percentile pct, return zero if empty, +// the pct's valid range is be [0, 1], it will be treated as 1 if greater than 1, as 0 if smaller than 0 func (s *IntSeq) Percentile(pct float64) Int { s.buildIndex() if len(s.slice) == 0 { @@ -232,11 +259,13 @@ func (s *IntSeq) Percentile(pct float64) Int { return s.slice[s.valueSlice[i]] } +// Range return a sub *IntSeq with specified interval func (s *IntSeq) Range(interval Interval) *IntSeq { slice := Range(s.slice, interval).(Ints) return newIntSeq(slice) } +// Merge merge slices to inside slice according to the specified rule func (s *IntSeq) Merge(fn func(t time.Time, v1, v2 *int) *int, slices ...Ints) error { if fn == nil { return errors.New("nil fn") @@ -304,6 +333,7 @@ func (s *IntSeq) Merge(fn func(t time.Time, v1, v2 *int) *int, slices ...Ints) e return nil } +// Aggregate aggregate inside slice according to the specified rule func (s *IntSeq) Aggregate(fn func(t time.Time, slice Ints) *int, duration time.Duration, interval Interval) error { if fn == nil { return errors.New("nil fn") @@ -365,6 +395,7 @@ func (s *IntSeq) Aggregate(fn func(t time.Time, slice Ints) *int, duration time. return nil } +// Trim remove the elements which make fn return true func (s *IntSeq) Trim(fn func(i int, v Int) bool) error { if fn == nil { return errors.New("nil fn") @@ -387,6 +418,7 @@ func (s *IntSeq) Trim(fn func(i int, v Int) bool) error { return nil } +// Clone return a new *IntSeq with copied slice inside func (s *IntSeq) Clone() *IntSeq { if s == nil { return nil diff --git a/gen_int_seq_test.go b/gen_int_seq_test.go index 249274b..a081a6d 100644 --- a/gen_int_seq_test.go +++ b/gen_int_seq_test.go @@ -335,7 +335,7 @@ func TestIntSeq_MValue(t *testing.T) { } } -func TestIntSeq_Visit(t *testing.T) { +func TestIntSeq_Traverse(t *testing.T) { data := RandomInts(100) type args struct { @@ -365,7 +365,7 @@ func TestIntSeq_Visit(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { s := NewIntSeq(data) - s.Visit(tt.args.fn) + s.Traverse(tt.args.fn) }) } } diff --git a/gen_uint64_seq.go b/gen_uint64_seq.go index 94fe662..7aca29d 100644 --- a/gen_uint64_seq.go +++ b/gen_uint64_seq.go @@ -9,37 +9,46 @@ import ( "time" ) +// Uint64 is a time point with uint64 value inside type Uint64 struct { Time time.Time Value uint64 } +// IsZero return if time and value are both zero func (v Uint64) IsZero() bool { return v.Value == 0 && v.Time.IsZero() } +// IsZero return if time and value are both equal func (v Uint64) Equal(n Uint64) bool { return v.Value == n.Value && v.Time.Equal(n.Time) } +// Uint64s is a alias of Uint64 slice type Uint64s []Uint64 +// Len implements Interface.Len() func (s Uint64s) Len() int { return len(s) } +// Swap implements Interface.Swap() func (s Uint64s) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +// Time implements Interface.Time() func (s Uint64s) Time(i int) time.Time { return s[i].Time } +// Slice implements Interface.Slice() func (s Uint64s) Slice(i, j int) Interface { return s[i:j] } +// Uint64Seq is a wrapper with useful methods of Uint64 slice type Uint64Seq struct { slice Uint64s @@ -49,12 +58,14 @@ type Uint64Seq struct { valueSlice []int } +// NewUint64Seq return *Uint64Seq with copied slice inside func NewUint64Seq(slice Uint64s) *Uint64Seq { temp := make(Uint64s, len(slice)) copy(temp, slice) return WrapUint64Seq(temp) } +// WrapUint64Seq return *Uint64Seq with origin slice inside func WrapUint64Seq(slice Uint64s) *Uint64Seq { if !IsSorted(slice) { Sort(slice) @@ -93,16 +104,19 @@ func (s *Uint64Seq) resetIndex() { s.indexOnce = sync.Once{} } +// Uint64s return a replica of inside slice func (s *Uint64Seq) Uint64s() Uint64s { slice := make(Uint64s, len(s.slice)) copy(slice, s.slice) return slice } +// Len return length of inside slice func (s *Uint64Seq) Len() int { return len(s.slice) } +// Index return element of inside slice, return zero if index is out of range func (s *Uint64Seq) Index(i int) Uint64 { if i < 0 || i >= len(s.slice) { return Uint64{} @@ -110,6 +124,7 @@ func (s *Uint64Seq) Index(i int) Uint64 { return s.slice[i] } +// Time return the first element with time t, return zero if not found func (s *Uint64Seq) Time(t time.Time) Uint64 { got := s.MTime(t) if len(got) == 0 { @@ -118,6 +133,7 @@ func (s *Uint64Seq) Time(t time.Time) Uint64 { return got[0] } +// MTime return all elements with time t, return nil if not found func (s *Uint64Seq) MTime(t time.Time) Uint64s { s.buildIndex() index := s.timeIndex[newTimeKey(t)] @@ -131,6 +147,7 @@ func (s *Uint64Seq) MTime(t time.Time) Uint64s { return ret } +// Value return the first element with value v, return zero if not found func (s *Uint64Seq) Value(v uint64) Uint64 { got := s.MValue(v) if len(got) == 0 { @@ -139,6 +156,7 @@ func (s *Uint64Seq) Value(v uint64) Uint64 { return got[0] } +// MValue return all elements with value v, return nil if not found func (s *Uint64Seq) MValue(v uint64) Uint64s { s.buildIndex() index := s.valueIndex[v] @@ -152,7 +170,8 @@ func (s *Uint64Seq) MValue(v uint64) Uint64s { return ret } -func (s *Uint64Seq) Visit(fn func(i int, v Uint64) (stop bool)) { +// Traverse call fn for every element one by one, break if fn return true +func (s *Uint64Seq) Traverse(fn func(i int, v Uint64) (stop bool)) { for i, v := range s.slice { if fn != nil && fn(i, v) { break @@ -160,6 +179,7 @@ func (s *Uint64Seq) Visit(fn func(i int, v Uint64) (stop bool)) { } } +// Sum return sum of all values func (s *Uint64Seq) Sum() uint64 { var ret uint64 for _, v := range s.slice { @@ -168,10 +188,12 @@ func (s *Uint64Seq) Sum() uint64 { return ret } +// Count return count of elements, same as Len func (s *Uint64Seq) Count() int { return s.Len() } +// Max return the element with max value, return zero if empty func (s *Uint64Seq) Max() Uint64 { var max Uint64 found := false @@ -186,6 +208,7 @@ func (s *Uint64Seq) Max() Uint64 { return max } +// Max return the element with min value, return zero if empty func (s *Uint64Seq) Min() Uint64 { var min Uint64 found := false @@ -200,6 +223,7 @@ func (s *Uint64Seq) Min() Uint64 { return min } +// First return the first element, return zero if empty func (s *Uint64Seq) First() Uint64 { if len(s.slice) == 0 { return Uint64{} @@ -207,6 +231,7 @@ func (s *Uint64Seq) First() Uint64 { return s.slice[0] } +// Last return the last element, return zero if empty func (s *Uint64Seq) Last() Uint64 { if len(s.slice) == 0 { return Uint64{} @@ -214,6 +239,8 @@ func (s *Uint64Seq) Last() Uint64 { return s.slice[len(s.slice)-1] } +// Percentile return the element matched with percentile pct, return zero if empty, +// the pct's valid range is be [0, 1], it will be treated as 1 if greater than 1, as 0 if smaller than 0 func (s *Uint64Seq) Percentile(pct float64) Uint64 { s.buildIndex() if len(s.slice) == 0 { @@ -232,11 +259,13 @@ func (s *Uint64Seq) Percentile(pct float64) Uint64 { return s.slice[s.valueSlice[i]] } +// Range return a sub *Uint64Seq with specified interval func (s *Uint64Seq) Range(interval Interval) *Uint64Seq { slice := Range(s.slice, interval).(Uint64s) return newUint64Seq(slice) } +// Merge merge slices to inside slice according to the specified rule func (s *Uint64Seq) Merge(fn func(t time.Time, v1, v2 *uint64) *uint64, slices ...Uint64s) error { if fn == nil { return errors.New("nil fn") @@ -304,6 +333,7 @@ func (s *Uint64Seq) Merge(fn func(t time.Time, v1, v2 *uint64) *uint64, slices . return nil } +// Aggregate aggregate inside slice according to the specified rule func (s *Uint64Seq) Aggregate(fn func(t time.Time, slice Uint64s) *uint64, duration time.Duration, interval Interval) error { if fn == nil { return errors.New("nil fn") @@ -365,6 +395,7 @@ func (s *Uint64Seq) Aggregate(fn func(t time.Time, slice Uint64s) *uint64, durat return nil } +// Trim remove the elements which make fn return true func (s *Uint64Seq) Trim(fn func(i int, v Uint64) bool) error { if fn == nil { return errors.New("nil fn") @@ -387,6 +418,7 @@ func (s *Uint64Seq) Trim(fn func(i int, v Uint64) bool) error { return nil } +// Clone return a new *Uint64Seq with copied slice inside func (s *Uint64Seq) Clone() *Uint64Seq { if s == nil { return nil diff --git a/gen_uint64_seq_test.go b/gen_uint64_seq_test.go index 1e96625..85556fb 100644 --- a/gen_uint64_seq_test.go +++ b/gen_uint64_seq_test.go @@ -335,7 +335,7 @@ func TestUint64Seq_MValue(t *testing.T) { } } -func TestUint64Seq_Visit(t *testing.T) { +func TestUint64Seq_Traverse(t *testing.T) { data := RandomUint64s(100) type args struct { @@ -365,7 +365,7 @@ func TestUint64Seq_Visit(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { s := NewUint64Seq(data) - s.Visit(tt.args.fn) + s.Traverse(tt.args.fn) }) } } diff --git a/timeseq.go b/timeseq.go index 81f77dc..812d8c9 100644 --- a/timeseq.go +++ b/timeseq.go @@ -6,6 +6,7 @@ import ( "time" ) +// Interface is a type which can be sorted according to time type Interface interface { // return length Len() int @@ -53,11 +54,13 @@ func Range(slice Interface, interval Interval) Interface { return slice.Slice(i, j) } +// Interval indicates a continuous time range type Interval struct { NotBefore *time.Time NotAfter *time.Time } +// Contain return if time t is in the interval func (i Interval) Contain(t time.Time) bool { if i.NotAfter != nil && t.After(*i.NotAfter) { return false @@ -68,14 +71,17 @@ func (i Interval) Contain(t time.Time) bool { return true } +// BeginAt is alias of AfterOrEqual func (i Interval) BeginAt(t time.Time) Interval { return i.AfterOrEqual(t) } +// EndAt is alias of BeforeOrEqual func (i Interval) EndAt(t time.Time) Interval { return i.BeforeOrEqual(t) } +// BeforeOrEqual return a new Interval which not before t func (i Interval) BeforeOrEqual(t time.Time) Interval { return Interval{ NotBefore: i.NotBefore, @@ -83,6 +89,7 @@ func (i Interval) BeforeOrEqual(t time.Time) Interval { } } +// AfterOrEqual return a new Interval which not after t func (i Interval) AfterOrEqual(t time.Time) Interval { return Interval{ NotBefore: &t, @@ -90,6 +97,7 @@ func (i Interval) AfterOrEqual(t time.Time) Interval { } } +// Before return a new Interval which before t func (i Interval) Before(t time.Time) Interval { t = t.Add(-1) return Interval{ @@ -98,6 +106,7 @@ func (i Interval) Before(t time.Time) Interval { } } +// After return a new Interval which after t func (i Interval) After(t time.Time) Interval { t = t.Add(1) return Interval{ @@ -106,26 +115,31 @@ func (i Interval) After(t time.Time) Interval { } } +// BeginAt is alias of AfterOrEqual func BeginAt(t time.Time) Interval { return AfterOrEqual(t) } +// EndAt is alias of BeforeOrEqual func EndAt(t time.Time) Interval { return BeforeOrEqual(t) } +// BeforeOrEqual return a new Interval which not before t func BeforeOrEqual(t time.Time) Interval { return Interval{ NotAfter: &t, } } +// AfterOrEqual return a new Interval which not after t func AfterOrEqual(t time.Time) Interval { return Interval{ NotBefore: &t, } } +// Before return a new Interval which before t func Before(t time.Time) Interval { t = t.Add(-1) return Interval{ @@ -133,6 +147,7 @@ func Before(t time.Time) Interval { } } +// After return a new Interval which after t func After(t time.Time) Interval { t = t.Add(1) return Interval{ @@ -140,15 +155,15 @@ func After(t time.Time) Interval { } } -type timeKey [16]byte +type timeKey [12]byte -//func (k timeKey) Get() time.Time { -// return time.Unix(int64(binary.BigEndian.Uint64(k[:8])), int64(binary.BigEndian.Uint64(k[8:]))) -//} +func (k timeKey) Time() time.Time { + return time.Unix(int64(binary.BigEndian.Uint64(k[:8])), int64(binary.BigEndian.Uint32(k[8:]))) +} func newTimeKey(t time.Time) timeKey { - var ret [16]byte + var ret [12]byte binary.BigEndian.PutUint64(ret[:8], uint64(t.Unix())) - binary.BigEndian.PutUint64(ret[8:], uint64(t.UnixNano())) + binary.BigEndian.PutUint32(ret[8:], uint32(t.Nanosecond())) return ret } diff --git a/timeseq_test.go b/timeseq_test.go index f6bef72..84735b7 100644 --- a/timeseq_test.go +++ b/timeseq_test.go @@ -129,3 +129,26 @@ func TestInterval_Contain(t *testing.T) { }) } } + +func Test_timeKey_Time(t *testing.T) { + now := time.Now() + + tests := []struct { + name string + k timeKey + want time.Time + }{ + { + name: "regular", + k: newTimeKey(now), + want: now, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.k.Time(); !got.Equal(tt.want) { + t.Errorf("Time() = %v, want %v", got, tt.want) + } + }) + } +}