Перейти к основному содержимому
Модуль 4 · Урок 5 из 520/50 в курсе~10 min
Уроки модуля (5/5)

Сортировка с помощью пакета sort

Стандартный пакет sort сортирует фрагменты на месте. Для базовых типов (int, float64, string) есть прямые помощники; за любой другой кусочек тебя используйте sort.Slice с функцией less(i, j int) bool, которая определяет заказ.

Помощники для базовых типов

Go
import "sort"

nums := []int{5, 2, 8, 1}
sort.Ints(nums)        // [1 2 5 8]

words := []string{"c", "a", "b"}
sort.Strings(words)    // [a b c]

fs := []float64{1.5, 0.5, 2.5}
sort.Float64s(fs)      // [0.5 1.5 2.5]

Сортировка осуществляется на месте: исходный фрагмент мутирует.

sort.Slice: пользовательская сортировка

Вы передаете срез и функцию less, которая, учитывая два индекса i и j возвращает true, если элемент i должен предшествовать j:

Go
type Person struct {
    Name string
    Age  int
}

people := []Person{
    {"Bruno", 30},
    {"Anna", 25},
    {"Carla", 28},
}

sort.Slice(people, func(i, j int) bool {
    return people[i].Age < people[j].Age
})
// Anna(25), Carla(28), Bruno(30)

Чтобы отсортировать в обратном порядке, просто переверните сравнение: return people[i].Age > people[j].Age.

Стабильная сортировка

sort.Slice не гарантирует стабильность (равные элементы могут меняться). относительный порядок). Для стабильной сортировки используйте sort.SliceStable:

Go
sort.SliceStable(people, func(i, j int) bool {
    return people[i].Age < people[j].Age
})

Сортировка по нескольким ключам

Общий шаблон: сортировка по возрасту и для одинаковых возрастов по имени:

Go
sort.Slice(people, func(i, j int) bool {
    if people[i].Age != people[j].Age {
        return people[i].Age < people[j].Age
    }
    return people[i].Name < people[j].Name
})

Бинарный поиск

sort.SearchInts / sort.Search работают с уже отсортированными фрагментами:

Go
nums := []int{1, 3, 5, 7, 9}
i := sort.SearchInts(nums, 5)   // 2

Если элемента нет, он возвращает индекс вставки. Вы можете копать в детали, когда они вам нужны.

Дженерики (Go 1.21+): slices.Sort

Из пакета slices в stdlib (Go 1.21):

Go
import "slices"

nums := []int{3, 1, 2}
slices.Sort(nums)               // [1 2 3]
slices.SortFunc(people, func(a, b Person) int {
    return a.Age - b.Age        // -1/0/1
})

Более современный, типобезопасный API. Совместим с sort.Slice и более эргономичный.

Попробуйте это

Упражнение#go.m4.l5.e1
Попыток: 0Загрузка…

Сортируйте числа в порядке возрастания, используя sort.Ints.

Загрузка редактора…
Показать подсказку

`sort.Ints` сортирует фрагмент целого числа на месте.

Решение доступно после 3 попыток

Упражнение#go.m4.l5.e2
Попыток: 0Загрузка…

Сортируйте людей по возрасту в порядке возрастания с помощью sort.Slice.

Загрузка редактора…
Показать подсказку

Функция less возвращает true, когда элемент i должен появиться ДО j.

Решение доступно после 3 попыток

Quiz#go.m4.l5.e3
Готово

Как выполнить сортировку по убыванию с помощью sort.Slice?

Go
sort.Slice(s, func(i, j int) bool { return ??? })
Варианты ответа

Резюме

  • sort.Ints / sort.Strings / sort.Float64s для базовых типов, на месте.
  • sort.Slice(s, less) для фрагментов любого типа с функцией less(i, j).
  • sort.SliceStable для сохранения относительного порядка одинаковых ключей.
  • Сортировка по нескольким ключам: каскад if внутри less.
  • Перейти 1.21+: пакет slices с общим API (slices.Sort, slices.SortFunc).
  • Для ключей карты: извлеките на срез и отсортируйте.