如何按多个值对Go切片进行排序?

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

How do I sort a go slice by multiple values?

问题

我有一个类似上面的结构体切片。如何按照X值首先排序,然后按照Y值排序,就像在SQL中使用ORDER BY X,Y一样?

我看到你可以使用sort.Slice()自Go 1.8版本以来,但是否有一种简单的方法可以在不多次循环切片的情况下解决这个问题?

英文:
type Item struct {
	Y    int
	X    int
	otherProp    int
}

I have a slice of structs like the above one. How do I sort the slice item []Item by the X value first and then by the Y value like in SQLs ORDER BY X,Y?

I see that you can use sort.Slice() since go 1.8 but is there a simple way to solve this without looping over the slice several times?

答案1

得分: 2

根据这里的第一个示例:Package sort,我编写了以下代码...

Less()函数中,我检查X是否相等,如果相等,则检查Y

playground演示

package main

import (
	"fmt"
	"sort"
)

type Item struct {
    X    int
    Y    int
    otherProp    int
}

func (i Item) String() string {
	return fmt.Sprintf("X: %d, Y: %d, otherProp: %d\n", i.X, i.Y, i.otherProp)
}

// ByX 根据 X 字段为 []Item 实现 sort.Interface 接口。
type ByX []Item

func (o ByX) Len() int           { return len(o) }
func (o ByX) Swap(i, j int)      { o[i], o[j] = o[j], o[i] }
func (o ByX) Less(i, j int) bool { 
	if o[i].X == o[j].X {
		return o[i].Y < o[j].Y
	} else {
		return o[i].X < o[j].X
	}
}

func main() {
	items := []Item{
		{1,2,3},
		{5,2,3},
		{3,2,3},
		{9,2,3},
		{1,1,3},
		{1,0,3},
	}

	fmt.Println(items)
	sort.Sort(ByX(items))
	fmt.Println(items)

}

输出:

[X: 1, Y: 2, otherProp: 3
 X: 5, Y: 2, otherProp: 3
 X: 3, Y: 2, otherProp: 3
 X: 9, Y: 2, otherProp: 3
 X: 1, Y: 1, otherProp: 3
 X: 1, Y: 0, otherProp: 3
]
[X: 1, Y: 0, otherProp: 3
 X: 1, Y: 1, otherProp: 3
 X: 1, Y: 2, otherProp: 3
 X: 3, Y: 2, otherProp: 3
 X: 5, Y: 2, otherProp: 3
 X: 9, Y: 2, otherProp: 3
]
英文:

Following the first example from here: Package sort, I wrote the following...

Inside the Less() function I check if X are equal and if so, I then check Y.

playground demo

package main

import (
	&quot;fmt&quot;
	&quot;sort&quot;
)

type Item struct {
    X    int
    Y    int
    otherProp    int
}

func (i Item) String() string {
	return fmt.Sprintf(&quot;X: %d, Y: %d, otherProp: %d\n&quot;, i.X, i.Y, i.otherProp)
}

// ByX implements sort.Interface for []Item based on
// the X field.
type ByX []Item

func (o ByX) Len() int           { return len(o) }
func (o ByX) Swap(i, j int)      { o[i], o[j] = o[j], o[i] }
func (o ByX) Less(i, j int) bool { 
	if o[i].X == o[j].X {
		return o[i].Y &lt; o[j].Y
	} else {
		return o[i].X &lt; o[j].X
	}
}

func main() {
	items := []Item{
		{1,2,3},
		{5,2,3},
		{3,2,3},
		{9,2,3},
		{1,1,3},
		{1,0,3},
	}

	fmt.Println(items)
	sort.Sort(ByX(items))
	fmt.Println(items)

}

output:

[X: 1, Y: 2, otherProp: 3
 X: 5, Y: 2, otherProp: 3
 X: 3, Y: 2, otherProp: 3
 X: 9, Y: 2, otherProp: 3
 X: 1, Y: 1, otherProp: 3
 X: 1, Y: 0, otherProp: 3
]
[X: 1, Y: 0, otherProp: 3
 X: 1, Y: 1, otherProp: 3
 X: 1, Y: 2, otherProp: 3
 X: 3, Y: 2, otherProp: 3
 X: 5, Y: 2, otherProp: 3
 X: 9, Y: 2, otherProp: 3
]

答案2

得分: 1

有没有一种简单的方法可以在不多次循环切片的情况下解决这个问题?

没有。基于比较的排序基本上总是需要至少一次循环切片加上一些额外的操作。但不用担心:sort.Slice并不会做太多的工作。

你有什么问题吗?

英文:

> [...] is there a simple way to solve this without looping over the slice several times?

No. Comparison-based sorting basically always involves looping over the slice at least once plus a bit more. But do not worry: sort.Slice does not do too much work.

What's your question?

huangapple
  • 本文由 发表于 2017年9月13日 21:50:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/46199397.html
匿名

发表评论

匿名网友

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

确定