如何稳定地反向排序 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)
}