package main
import (
"fmt"
"sort"
"time"
)
type Invoice struct {
Id int64
Due time.Time
}
type Invoices []Invoice
func (s Invoices) Len() int {
return len(s)
}
func (s Invoices) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s Invoices) Less(i, j int) bool {
return s[i].Due.Before(s[j].Due)
}
func main() {
day := 1*24*time.Hour
is := Invoices{
{1, time.Now()},
{2, time.Now().Add(1*day)},
{3, time.Now().Add(2*day)},
{4, time.Now().Add(5*day)},
{5, time.Now().Add(7*day)},
{6, time.Now().Add(-1*day)},
{7, time.Now().Add(-2*day)},
}
sort.Sort(is)
limit := time.Now().Add(1*day)
for i, v := range is {
if v.Due.After(limit) {
is = is[:i]
break
}
}
fmt.Println(is)
}
# go run slice.go
[{7 2012-02-18 22:21:57.285126 +0100 CET} {6 2012-02-19
22:21:57.285126 +0100 CET} {1 2012-02-20 22:21:57.285126 +0100 CET} {2
2012-02-21 22:21:57.285126 +0100 CET}]
type Activity struct {
Id int64
Start time.Time
End time.Time
}
type Activities []Activity
1) Your code helps to e.g. sort after Start and filter all activities starting before end of one chosen day.
2) How could I sort afterwards (means the interim result of 1) after End and filter all activities ending after beginning of chosen day.
I'm not sure I completely understand your question, but if you wanted
to you could make a similar construction where Invoices.Less returns
i.End.Less(j.End), and do "is = is[i:]" instead of "is = is[:i]" in
the for loop to get the later ones (since the slice is sorted by
date.)
If you want to get more advanced you could change your type to a
Struct, add a "SortBy" field, set that before sorting, and then vary
the output from Less/Swap/Len according to s.SortBy. (Or make a struct
with func fields "less", "swap", "len", change the Less/Swap/Len to
just return s.less(i, j)/s.swap(i, j), s.len(), and then set those
fields to what you want.)
If you want to be able to sort in very different ways, you can make
several types with varying Less/Swap/Len methods, then cast your slice
to the appropriate one when passing it to sort, e.g.:
type InvoicesByEnd []Invoices
func (s InvoicesByEnd) Len() {
...
}
func (s InvoicesByEnd) Less(i, j) {
...
}
func (s InvoicesByEnd) Swap(i, j) {
...
}
s := []Invoices{
foo,
bar,
baz,
}
sort.Sort(s.(InvoicesByEnd))
But at some point, looking into "database/sql" might be a better idea? :)
How would you sort a slice of structs by a certain field if you don't
indicate that e.g. by satisfying the interface with custom methods?
(The example sorts []Struct, not []time.Time)
Apropos, sort.SortBy(slice, "fieldname") (using reflect) might be an
interesting addition to the sort package?