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)
}

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

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 и реализуете несколько стратегий сортировки, что позволит сортировать одну и ту же collection разными способами.

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

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

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

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

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

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

  • main.go: создайте и отсортируйте inventory продуктов.

    Прочитайте режим сортировки (price или quantity), затем прочитайте count и сведения о продуктах. Каждый продукт задаётся тремя строками: имя, цена и количество.

    Создайте срез продуктов, отсортируйте его с помощью соответствующего типа сортировки на основе режима, затем выведите каждый продукт в следующем формате:

    [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"
	"strings"
)

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 = strings.TrimSpace(name)

		priceStr, _ := reader.ReadString('\n')
		priceStr = strings.TrimSpace(priceStr)
		price, _ := strconv.ParseFloat(priceStr, 64)

		qtyStr, _ := reader.ReadString('\n')
		qtyStr = strings.TrimSpace(qtyStr)
		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