如何稳定地反向排序 Go 中的一个切片?
How to stable reverse sort a slice in Go?
我有
4, 5', 6, 5''
并希望将稳定排序反转为
6, 5', 5'', 4
但不是
6, 5'', 5', 4
此(无效)代码无效
keys := []int{4, 5', 6, 5''}
sort.Stable(sort.Reverse(sort.Ints(keys)))
它将产生:
6, 5'', 5', 4
这里问题被简化为整数切片,但实际上我需要将它应用于结构切片
type myStruct struct {
t time.Time
d time.Duration
}
和基于 t
字段的反向稳定排序。
编辑:经过一些评论后,我明确指出整数 1 是一个无法工作的示例,以简化问题。
在切片类型上实现sort.Interface
接口,这样您就可以选择排序顺序,并对其应用稳定排序。示例:https://play.golang.org/p/TWAtH7asi3
在您的自定义结构上实现 sort.Interface
接口。
type myStruct struct{
t time.Time
d time.Duration
}
type Slice []myStruct
func (s Slice) Len() int { return len(s) }
func (s Slice) Less(i, j int) bool {
return (s[i].t).After(s[j].t)
}
func (s Slice) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
在您的情况下,以下函数将根据 t
倒序排序
func (s Slice) Less(i, j int) bool {
return (s[i].t).After(s[j].t)
}
(s[i].t).After(s[j].t)
报告 s[i].t
是否在 s[j].t
.
之后
如果你只想排序,使用下面的
func (s Slice) Less(i, j int) bool {
return (s[i].t).Before(s[j].t)
}
希望这会有所帮助。
看来您不需要经历实现排序接口的麻烦。您可以使用 sort.Slice or sort.SliceStable.
进行裸排序
以下是对我有用的方法 (go playground):
package main
import (
"fmt"
"sort"
"time"
)
func main() {
layout := "Jan 2 15:04:05 -0700 MST 2006"
t1, _ := time.Parse(layout, "Jan 2 15:04:05 -0700 MST 2008")
t2, _ := time.Parse(layout, "Jan 2 15:04:05 -0700 MST 2001")
t3, _ := time.Parse(layout, "Jan 2 15:04:05 -0700 MST 2003")
t4, _ := time.Parse(layout, "Jan 2 15:04:05 -0700 MST 2006")
timestamps := []struct {
T time.Time
d time.Duration
}{
{t1, 1},
{t2, 1},
{t3, 1},
{t4, 1},
}
// forward
sort.Slice(timestamps, func(i, j int) bool {
return timestamps[i].T.Before(timestamps[j].T)
})
fmt.Println("By time:", timestamps)
// reverse
sort.Slice(timestamps, func(i, j int) bool {
return timestamps[i].T.After(timestamps[j].T)
})
fmt.Println("By time:", timestamps)
}
我有
4, 5', 6, 5''
并希望将稳定排序反转为
6, 5', 5'', 4
但不是
6, 5'', 5', 4
此(无效)代码无效
keys := []int{4, 5', 6, 5''}
sort.Stable(sort.Reverse(sort.Ints(keys)))
它将产生:
6, 5'', 5', 4
这里问题被简化为整数切片,但实际上我需要将它应用于结构切片
type myStruct struct {
t time.Time
d time.Duration
}
和基于 t
字段的反向稳定排序。
编辑:经过一些评论后,我明确指出整数 1 是一个无法工作的示例,以简化问题。
在切片类型上实现sort.Interface
接口,这样您就可以选择排序顺序,并对其应用稳定排序。示例:https://play.golang.org/p/TWAtH7asi3
在您的自定义结构上实现 sort.Interface
接口。
type myStruct struct{
t time.Time
d time.Duration
}
type Slice []myStruct
func (s Slice) Len() int { return len(s) }
func (s Slice) Less(i, j int) bool {
return (s[i].t).After(s[j].t)
}
func (s Slice) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
在您的情况下,以下函数将根据 t
func (s Slice) Less(i, j int) bool {
return (s[i].t).After(s[j].t)
}
(s[i].t).After(s[j].t)
报告 s[i].t
是否在 s[j].t
.
如果你只想排序,使用下面的
func (s Slice) Less(i, j int) bool {
return (s[i].t).Before(s[j].t)
}
希望这会有所帮助。
看来您不需要经历实现排序接口的麻烦。您可以使用 sort.Slice or sort.SliceStable.
进行裸排序以下是对我有用的方法 (go playground):
package main
import (
"fmt"
"sort"
"time"
)
func main() {
layout := "Jan 2 15:04:05 -0700 MST 2006"
t1, _ := time.Parse(layout, "Jan 2 15:04:05 -0700 MST 2008")
t2, _ := time.Parse(layout, "Jan 2 15:04:05 -0700 MST 2001")
t3, _ := time.Parse(layout, "Jan 2 15:04:05 -0700 MST 2003")
t4, _ := time.Parse(layout, "Jan 2 15:04:05 -0700 MST 2006")
timestamps := []struct {
T time.Time
d time.Duration
}{
{t1, 1},
{t2, 1},
{t3, 1},
{t4, 1},
}
// forward
sort.Slice(timestamps, func(i, j int) bool {
return timestamps[i].T.Before(timestamps[j].T)
})
fmt.Println("By time:", timestamps)
// reverse
sort.Slice(timestamps, func(i, j int) bool {
return timestamps[i].T.After(timestamps[j].T)
})
fmt.Println("By time:", timestamps)
}