Menu
Coddy logo textTech

sort.Interface

Часть раздела Объектно-ориентированное программирование путешествия по GO на Coddy. Урок 74 из 107.

Пакет sort предоставляет еще один отличный пример проектирования на основе интерфейсов. Чтобы отсортировать пользовательскую коллекцию, ваш тип должен реализовать sort.Interface:

type Interface interface {
    Len() int
    Less(i, j int) bool
    Swap(i, j int)
}

Эти три метода дают алгоритму сортировки всё необходимое: длину коллекции, способ сравнения элементов и способ их перестановки. Вот как сделать слайс пользовательских структур сортируемым:

type Person struct {
    Name string
    Age  int
}

type ByAge []Person

func (a ByAge) Len() int           { return len(a) }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
func (a ByAge) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }

func main() {
    people := []Person{
        {"Alice", 30},
        {"Bob", 25},
        {"Carol", 35},
    }
    
    sort.Sort(ByAge(people))
    fmt.Println(people)
    // [{Bob 25} {Alice 30} {Carol 35}]
}

Ключевая идея заключается в создании именованного типа (ByAge) на основе вашего среза. Это позволяет определять различное поведение сортировки для одних и тех же данных. Вы могли бы создать ByName с другой реализацией Less, чтобы вместо этого выполнять сортировку по алфавиту.

Как только ваш тип начнет удовлетворять sort.Interface, он автоматически заработает с sort.Sort(), sort.Reverse() и sort.IsSorted().

challenge icon

Задание

Легко

Давайте создадим систему инвентаризации товаров с возможностью сортировки, которая продемонстрирует мощь интерфейса sort.Interface в Go! Вы создадите тип Product и реализуете несколько стратегий сортировки, что позволит сортировать одну и ту же коллекцию разными способами.

Вы организуете свой код в двух файлах:

  • product.go: Определите тип продукта и реализации сортировки.

    Создайте структуру Product с тремя полями: Name (string), Price (float64) и Quantity (int).

    Создайте два именованных типа на основе []Product:

    • ByPrice — для сортировки товаров по цене в порядке возрастания
    • ByQuantity — для сортировки товаров по количеству в порядке убывания (сначала наибольшее количество)

    Каждый тип должен реализовать три метода, требуемых интерфейсом sort.Interface: Len(), Less(i, j int) и Swap(i, j int). Метод Less определяет порядок сортировки для каждого типа.

  • main.go: Создайте и отсортируйте ваш инвентарь товаров.

    Считайте режим сортировки (price или quantity), затем считайте количество товаров, а после — детали каждого товара. Каждый товар представлен тремя строками: название, цена и количество.

    Создайте срез (slice) товаров, отсортируйте их, используя соответствующий тип сортировки в зависимости от режима, а затем выведите каждый товар в следующем формате:

    [Name]: $[Price] (x[Quantity])

    Выводите цены с двумя знаками после запятой.

Будут предоставлены следующие входные данные:

  • Строка 1: Режим сортировки (price или quantity)
  • Строка 2: Количество товаров
  • Последующие строки: Детали товара (название, цена, количество — по три строки на каждый товар)

Например, для входных данных:

price
3
Laptop
999.99
5
Mouse
29.99
50
Keyboard
79.99
25

Ваш вывод должен быть таким:

Mouse: $29.99 (x50)
Keyboard: $79.99 (x25)
Laptop: $999.99 (x5)

И для входных данных:

quantity
3
Laptop
999.99
5
Mouse
29.99
50
Keyboard
79.99
25

Ваш вывод должен быть таким:

Mouse: $29.99 (x50)
Keyboard: $79.99 (x25)
Laptop: $999.99 (x5)

Обратите внимание, как одни и те же данные о товарах могут быть отсортированы по-разному простым использованием другого именованного типа. Как только ваши типы начинают удовлетворять sort.Interface, они бесшовно работают с функцией sort.Sort() из стандартной библиотеки.

Попробуйте сами

package main

import (
	"bufio"
	"fmt"
	"os"
	"sort"
	"strconv"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	// Чтение режима сортировки
	var mode string
	fmt.Fscanln(reader, &mode)

	// Чтение количества товаров
	var count int
	fmt.Fscanln(reader, &count)

	// Чтение товаров
	products := make([]Product, count)
	for i := 0; i < count; i++ {
		name, _ := reader.ReadString('\n')
		name = name[:len(name)-1] // Удаление символа новой строки

		priceStr, _ := reader.ReadString('\n')
		priceStr = priceStr[:len(priceStr)-1]
		price, _ := strconv.ParseFloat(priceStr, 64)

		qtyStr, _ := reader.ReadString('\n')
		qtyStr = qtyStr[:len(qtyStr)-1]
		quantity, _ := strconv.Atoi(qtyStr)

		products[i] = Product{Name: name, Price: price, Quantity: quantity}
	}

	// TODO: Отсортировать товары в зависимости от режима
	// Если mode равен "price", использовать тип ByPrice
	// Если mode равен "quantity", использовать тип ByQuantity
	// Использовать sort.Sort() с соответствующим типом

	// TODO: Вывести каждый товар в формате:
	// [Name]: $[Price] (x[Quantity])
	// Использовать fmt.Printf с %.2f для форматирования цены
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор Go