如何在Go中稳定地对切片进行逆序排序?

huangapple go评论91阅读模式
英文:

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"字段进行稳定的逆排序。


编辑:在一些评论后,我明确说明整数示例是一个不起作用的示例,目的是简化问题。

英文:

I do have

4, 5', 6, 5''

and want to reverse stable sort as

6, 5', 5'', 4

but not

6, 5'', 5', 4

This (invalid) code would not work

keys := []int{4, 5', 6, 5''}
sort.Stable(sort.Reverse(sort.Ints(keys)))

it would produce:

6, 5'', 5', 4

Here the problem is shown as simplified as a slice of integers, but In reality I need to use it applied to a slice of structs

type myStruct struct {
	t time.Time
	d time.Duration
}

and reverse stable sort based in the t field.


Edit: After few comments I made explicit that the integer one is a non working example to simplify the problem.

答案1

得分: 2

在一个切片类型上实现sort.Interface接口,这样你就可以选择排序顺序,并对其应用稳定排序。示例:https://play.golang.org/p/TWAtH7asi3

英文:

Implement the sort.Interface interface on a slice type, so you can choose the sort order, and apply a stable sort on it. Example : https://play.golang.org/p/TWAtH7asi3

答案2

得分: 1

在你的自定义结构上实现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)
}

希望这能帮到你。

英文:

Implement the sort.Interface interface on your custom struct.

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]
}

In your case, following function will sort in reverse order based on t

func (s Slice) Less(i, j int) bool {
    return (s[i].t).After(s[j].t)
}

(s[i].t).After(s[j].t) reports whether s[i].t is after s[j].t.

If you want only sort, use following one

func (s Slice) Less(i, j int) bool {
    return (s[i].t).Before(s[j].t)
}

Hope this will help.

答案3

得分: 0

似乎你不需要费心实现排序接口。你可以直接使用sort.Slicesort.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},
	}

	// 正序排序
	sort.Slice(timestamps, func(i, j int) bool {
		return timestamps[i].T.Before(timestamps[j].T)
	})
	fmt.Println("按时间排序:", timestamps)

	// 逆序排序
	sort.Slice(timestamps, func(i, j int) bool {
		return timestamps[i].T.After(timestamps[j].T)
	})
	fmt.Println("按时间逆序排序:", timestamps)
}
英文:

It seems you don't need to go through the trouble of implementing the sort interface. You can just sort bare using sort.Slice or sort.SliceStable.

Here is what worked for me (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)
}

huangapple
  • 本文由 发表于 2017年1月16日 01:43:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/41664250.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定