голанг сортирует срез по возрастанию или убыванию

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

Пойдите на игровую площадку здесь, чтобы попробовать это самостоятельно.

Несколько примечательных моментов:

  1. Сортировка основных типов Go не требует реализации таких функций, как Len (), которые относятся к сортировке.Интерфейс. Вам нужно следовать этим маршрутом только для составных типов.
  2. Просто оберните тип базового типа, используя соответствующий поставщик методов интерфейса, например StringSlice, IntSlice или Float64Slice, и выполните сортировку.
  3. Срез сортируется на месте и, следовательно, не возвращает копию отсортированного среза.

Ответ №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]
}
 

оба должны возвращать один и тот же результат, но я думаю, что один из них более идиоматичен.

https://golang.org/pkg/sort#Slice

Ответ №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