# #sorting #go
Вопрос:
Мне нужно отсортировать фрагмент типа, который поступает из пакета 3-й партии. В зависимости от некоторых условий порядок должен быть восходящим или нисходящим.
Решение, которое я предлагаю, заключается в следующем:
type fooAscending []foo
func (v fooAscending) Len() int { return len(v) }
func (v fooAscending) Swap(i, j int) { v[i], v[j] = v[j], v[i] }
func (v fooAscending) Less(i, j int) bool { return v[i].Amount < v[j].Amount }
type fooDescending []foo
func (v fooDescending) Len() int { return len(v) }
func (v fooDescending) Swap(i, j int) { v[i], v[j] = v[j], v[i] }
func (v fooDescending) Less(i, j int) bool { return v[i].Amount > v[j].Amount }
if someCondition {
sort.Sort(fooAscending(array))
} else {
sort.Sort(fooDescending(array))
}
Есть ли лучший способ сделать это? 13 строк кода для этой задачи, и большая часть из них дублируется, кажется немного чересчур.
Ответ №1:
Начиная с версии 1.8, существует более простой способ сортировки среза, который не требует определения новых типов. Вы просто передаете анонимную функцию sort.Slice
функции.
a := []int{5, 3, 4, 7, 8, 9}
sort.Slice(a, func(i, j int) bool {
return a[i] < a[j]
})
for _, v := range a {
fmt.Println(v)
}
Это будет сортировка по возрастанию, если вы хотите обратного, просто напишите a[i] > a[j]
в анонимной функции.
Комментарии:
1. К сожалению, он ограничен типом int
2. @LewisChan это не ограничено типами int; параметры int являются индексами среза, который может быть срезом строк.
Ответ №2:
Ты ищешь sort.Reverse
. Это позволит вам сказать:
sort.Sort(sort.Reverse(fooAscending(s)))
Ответ №3:
Мой ответ ниже основан на предположении, что фрагмент, который вы получаете от стороннего пакета, относится к базовому типу Go.
Для сортировки срезов основных типов используйте утилиты сортировки пакетов. Вот пример сортировки фрагмента строки и фрагмента int.
package main
import (
"fmt"
"sort"
)
func main() {
sl := []string{"mumbai", "london", "tokyo", "seattle"}
sort.Sort(sort.StringSlice(sl))
fmt.Println(sl)
intSlice := []int{3,5,6,4,2,293,-34}
sort.Sort(sort.IntSlice(intSlice))
fmt.Println(intSlice)
}
Результатом вышесказанного является:
[london mumbai seattle tokyo]
[-34 2 3 4 5 6 293]
Пойдите на игровую площадку здесь, чтобы попробовать это самостоятельно.
Несколько примечательных моментов:
- Сортировка основных типов Go не требует реализации таких функций, как Len (), которые относятся к сортировке.Интерфейс. Вам нужно следовать этим маршрутом только для составных типов.
- Просто оберните тип базового типа, используя соответствующий поставщик методов интерфейса, например StringSlice, IntSlice или Float64Slice, и выполните сортировку.
- Срез сортируется на месте и, следовательно, не возвращает копию отсортированного среза.
Ответ №4:
Принятый ответ хорош, но я не согласен с их предложением о снижении:
a[i] > a[j]
С sort.Slice
помощью предоставленной функции предполагается , что она представляет собой
реализацию «меньше, чем».:
func Slice(x interface{}, less func(i, j int) bool)
Slice
сортирует срезx
с учетом предоставленнойless
функции. Он паникует, еслиx
это не кусочек.
Поэтому написание функции «больше, чем» на самом деле не соответствует данному описанию. Лучше было бы поменять местами индексы:
package main
import (
"fmt"
"sort"
)
func main() {
a := []int{5, 3, 4, 7, 8, 9}
sort.Slice(a, func(i, j int) bool {
return a[j] < a[i]
})
fmt.Println(a) // [9 8 7 5 4 3]
}
оба должны возвращать один и тот же результат, но я думаю, что один из них более идиоматичен.
Ответ №5:
вы можете импортировать пакет «сортировка» из стандартной библиотеки golang . затем вы можете использовать функцию «Нарезать» или «Нарезать» для сортировки своего среза. рекомендуется использовать второй такой :
sort.SliceStable(yourSlice , anonnymousFunction)
пример :
пакет основной
import (
"fmt"
"sort"
)
func main() {
a := []int{4,5,9,6,8,3,5,7,99,58,1}
sort.SliceStable(a, func(i,j int )bool{
//i,j are represented for two value of the slice .
return a[i] < a[j]
})
fmt.Println(a)
}
Ответ №6:
`var names = []string{"b", "a", "e", "c", "d"}
sort.Strings(names)
fmt.Println("Sorted in alphabetical order", names)
sort.Sort(sort.Reverse(sort.StringSlice(names)))
fmt.Println("Sorted in reverse order", names)`
ссылка для игры в Go Playgound https://play.golang.org/p/Q8KY_JE__kx