Menu
CoddyTech

sort.Interface

Thuộc phần Lập trình hướng đối tượng trong hành trình GO của Coddy. Bài học 74 trên 107.

Gói sort là một ví dụ tuyệt vời khác về thiết kế dựa trên giao diện. Để sắp xếp một tập hợp tùy chỉnh, kiểu của bạn phải triển khai sort.Interface:

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

Ba phương thức này cung cấp cho thuật toán sắp xếp mọi thứ cần thiết: độ dài của tập hợp, cách so sánh các phần tử và cách hoán đổi chúng. Sau đây là cách để sắp xếp một lát cắt gồm các struct tùy chỉnh:

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

Điểm mấu chốt là tạo một kiểu có tên (ByAge) dựa trên lát cắt của bạn. Nhờ đó, bạn có thể xác định các cách sắp xếp khác nhau cho cùng một dữ liệu. Bạn có thể tạo ByName với cách triển khai Less khác để sắp xếp theo thứ tự bảng chữ cái.

Khi kiểu dữ liệu của bạn đáp ứng sort.Interface, nó tự động hoạt động với sort.Sort(), sort.Reverse() và sort.IsSorted().

challenge icon

Thử thách

Dễ

Hãy xây dựng một hệ thống kiểm kê sản phẩm có thể sắp xếp để minh họa sức mạnh của sort.Interface trong Go! Bạn sẽ tạo kiểu Product và triển khai nhiều cách sắp xếp, giúp sắp xếp cùng một tập hợp theo nhiều cách khác nhau.

Bạn sẽ tổ chức code trong hai tệp:

  • product.go: Định nghĩa kiểu sản phẩm và các cách triển khai sắp xếp.

    Tạo một struct Product có ba trường: Name (chuỗi), Price (float64) và Quantity (int).

    Tạo hai kiểu có tên dựa trên []Product:

    • ByPrice - dùng để sắp xếp sản phẩm theo giá tăng dần
    • ByQuantity - dùng để sắp xếp sản phẩm theo số lượng giảm dần (số lượng cao nhất trước)

    Mỗi kiểu cần triển khai ba phương thức mà sort.Interface yêu cầu: Len(), Less(i, j int) và Swap(i, j int). Phương thức Less xác định thứ tự sắp xếp của từng kiểu.

  • main.go: Tạo và sắp xếp danh mục sản phẩm.

    Đọc chế độ sắp xếp (price hoặc quantity), sau đó đọc số lượng sản phẩm rồi đến thông tin chi tiết của từng sản phẩm. Mỗi sản phẩm được cung cấp trên ba dòng: tên, giá và số lượng.

    Tạo một slice sản phẩm, sắp xếp chúng bằng kiểu sắp xếp phù hợp dựa trên chế độ, sau đó in từng sản phẩm theo định dạng này:

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

    Hiển thị giá với hai chữ số thập phân.

Đầu vào sẽ có dạng như sau:

  • Dòng 1: Chế độ sắp xếp (price hoặc quantity)
  • Dòng 2: Số lượng sản phẩm
  • Các dòng tiếp theo: Thông tin chi tiết sản phẩm (tên, giá, số lượng, ba dòng cho mỗi sản phẩm)

Ví dụ, với đầu vào:

price
3
Laptop
999.99
5
Mouse
29.99
50
Keyboard
79.99
25

Đầu ra của bạn sẽ là:

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

Và với đầu vào:

quantity
3
Laptop
999.99
5
Mouse
29.99
50
Keyboard
79.99
25

Đầu ra của bạn sẽ là:

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

Lưu ý rằng cùng một dữ liệu sản phẩm có thể được sắp xếp theo nhiều cách khác nhau chỉ bằng cách dùng một kiểu có tên khác. Khi các kiểu của bạn đáp ứng sort.Interface, chúng sẽ hoạt động liền mạch với sort.Sort() trong thư viện chuẩn.

Tự làm thử

package main

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

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

	// Đọc chế độ sắp xếp
	var mode string
	fmt.Fscanln(reader, &mode)

	// Đọc số lượng sản phẩm
	var count int
	fmt.Fscanln(reader, &count)

	// Đọc các sản phẩm
	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: Sắp xếp sản phẩm theo mode
	// Nếu mode là "price", dùng kiểu ByPrice
	// Nếu mode là "quantity", dùng kiểu ByQuantity
	// Dùng sort.Sort() với kiểu phù hợp

	// TODO: In từng sản phẩm theo định dạng:
	// [Name]: $[Price] (x[Quantity])
	// Dùng fmt.Printf với %.2f để định dạng giá
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch Go online