по убыванию или по убыванию

Мне нужно отсортировать фрагмент типа, который идет из пакета 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] в анонимной функции.

Ответ 2

Вы ищете sort.Reverse. Это позволит вам сказать:

sort.Sort(sort.Reverse(fooAscending(s)))

Ответ 3

Мой ответ ниже основан на предположении, что фрагмент, который вы получаете от стороннего пакета, имеет базовый тип Go.

Для сортировки фрагментов основных типов используйте утилиты sort package. Вот пример, который сортирует фрагмент строки и фрагмент 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(), которые принадлежат sort.Interface. Вам нужно выбрать этот маршрут только для составных типов.

  2. Просто оберните тип базового типа с помощью соответствующего поставщика метода интерфейса, например, StringSlice, IntSlice или Float64Slice и сортируйте.

  3. Срез сортируется на месте и, следовательно, не возвращает копию отсортированного среза.