I have var keys []string
. A key represents the day and month formatted as either "D.MM"
or "DD.MM"
.
For example :
1.02 (1st of February) - 2.02 (2nd of February) - 1.03 (1st of March) - 3.02 (3rd of February) - 31.12 (31st of December)
I need the keys to be sorted as follows:
[ '1.02', '2.02', '3.02', '1.03', '31.12' ]
.
First the months, and then the days within the months.
I first tried to parse the string into a float64 number because I thought it would be easier to work with numbers (see the comments), but it seems it is worst.
How can I achieve this?
I suppose you need a Go program. Check this one:
package main
import (
"fmt"
"sort"
"strings"
)
type ByDay struct { sort.StringSlice }
func (a ByDay) Less(i, j int) bool {
dmi, dmj := strings.Split(a.StringSlice[i], "."), strings.Split(a.StringSlice[j], ".")
return dmi[1] < dmj[1] || dmi[1] == dmj[1] && dmi[0] < dmj[0]
}
func main() {
days := []string{"3.03", "3.02", "2.02", "3.01", "1.03", "1.02"}
sort.Sort(ByDay{days})
fmt.Println(days)
}
It prints [3.01 1.02 2.02 3.02 1.03 3.03]
.
I doubt ByDay
is the best name, you'd better give it a more descriptive one.
You need to use comparator function (As far as I see - go
provides such possibility) that separates string into two parts, compares the second parts, in case of equality compares the first part.
To provide correct comparison of days, transform string values to integers or just add '0' in the beginning if string length is 1 (to make '21' > '7')
pseudocode:
sort list with comparator func(a, b: string):
a => lefta, righta
b => leftb, rightb
if righta > rightb
return 1
else if righta < rightb
return -1
else:
if length(lefta)=1
lefta = '0' + lefta
if length(leftb)=1
leftb = '0' + leftb
if lefta > leftb
return 1
else if lefta < leftb
return -1
else
return 0
For example, an efficient conversion and comparison,
package main
import (
"fmt"
"sort"
)
func mmdd(key string) uint32 {
// "d.mm" or "dd.mm"
k := uint32(key[len(key)-1])<<16 +
uint32(key[len(key)-2])<<24 +
uint32(key[len(key)-4])<<0
if len(key) >= 5 {
k += uint32(key[len(key)-5]) << 8
}
return k
}
func main() {
// 1.02 (1st of February); 2.02 (2nd of February); 1.03 (1st of March); 3.02 (3rd of February)
keys := []string{"31.12", "01.01", "1.02", "2.02", "1.03", "3.02", "30.11"}
fmt.Println(keys)
sort.Slice(keys,
func(i, j int) bool {
return mmdd(keys[i]) < mmdd(keys[j])
},
)
fmt.Println(keys)
}
Output:
[31.12 01.01 1.02 2.02 1.03 3.02 30.11]
[01.01 1.02 2.02 3.02 1.03 30.11 31.12]