Перейти до основного вмісту
Модуль 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

Якщо елемента немає, він повертає індекс вставки. Можна копати в деталі, коли вони вам потрібні.

Generics (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` сортує зріз int на місці.

Рішення доступне після 3 спроб

вправи#go.m4.l5.e2
Спроби: 0Завантаження…

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

Завантаження редактора…
Показати підказку

Функція less повертає істину, коли елемент 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).
  • Для ключів карти: витягніть у фрагмент і відсортуйте.