Menu
Coddy logo textTech

sort.Interface

Coddy GO 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 107개 중 74번째.

sort 패키지는 인터페이스 기반 설계의 또 다른 훌륭한 예시를 제공합니다. 사용자 정의 컬렉션을 정렬하려면, 해당 타입은 sort.Interface를 구현해야 합니다:

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

이 세 가지 메서드는 정렬 알고리즘에 필요한 모든 것, 즉 컬렉션의 길이, 요소를 비교하는 방법, 그리고 요소를 교체하는 방법을 제공합니다. 다음은 사용자 정의 구조체(structs) 슬라이스를 정렬 가능하게 만드는 방법입니다.

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)을 생성하는 것입니다. 이를 통해 동일한 데이터에 대해 서로 다른 정렬 동작을 정의할 수 있습니다. 대신 알파벳 순으로 정렬하기 위해 다른 Less 구현을 가진 ByName을 생성할 수도 있습니다.

작성한 타입이 sort.Interface를 만족하면, sort.Sort(), sort.Reverse(), 그리고 sort.IsSorted()와 자동으로 함께 작동합니다.

challenge icon

챌린지

쉬움

Go의 sort.Interface의 강력함을 보여주는 정렬 가능한 제품 인벤토리 시스템을 구축해 봅시다! Product 타입을 만들고 여러 정렬 전략을 구현하여, 동일한 컬렉션을 다양한 방식으로 정렬할 수 있도록 할 것입니다.

코드는 두 개의 파일로 구성됩니다:

  • product.go: 제품 타입과 정렬 구현을 정의합니다.

    세 개의 필드 Name (string), Price (float64), Quantity (int)를 가진 Product 구조체를 생성하세요.

    []Product를 기반으로 하는 두 개의 명명된 타입(named types)을 생성하세요:

    • ByPrice - 제품을 가격 기준 오름차순으로 정렬하기 위함
    • ByQuantity - 제품을 수량 기준 내림차순(수량이 많은 순서)으로 정렬하기 위함

    각 타입은 sort.Interface에서 요구하는 세 가지 메서드인 Len(), Less(i, j int), Swap(i, j int)를 구현해야 합니다. Less 메서드가 각 타입의 정렬 순서를 결정합니다.

  • main.go: 제품 인벤토리를 구축하고 정렬합니다.

    정렬 모드(price 또는 quantity)를 읽은 다음, 제품 개수와 제품 상세 정보를 읽습니다. 각 제품은 이름, 가격, 수량의 세 줄로 제공됩니다.

    제품 슬라이스를 생성하고, 모드에 따라 적절한 정렬 타입을 사용하여 정렬한 후, 각 제품을 다음 형식으로 출력하세요:

    [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()와 완벽하게 연동됩니다.

치트 시트

sort 패키지는 타입을 정렬 가능하게 만들기 위해 sort.Interface를 구현하도록 요구합니다:

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

사용자 정의 슬라이스를 정렬 가능하게 만들려면, 명명된 타입(named type)을 생성하고 세 가지 필수 메서드를 구현하세요:

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

// 컬렉션 정렬
sort.Sort(ByAge(people))

동일한 슬라이스에 대해 여러 명명된 타입을 생성하여 서로 다른 정렬 동작을 구현할 수 있습니다. 각 타입은 정렬 순서를 결정하기 위해 자체 Less 메서드를 정의합니다.

타입이 sort.Interface를 충족하면 sort.Sort(), sort.Reverse(), 그리고 sort.IsSorted()와 함께 사용할 수 있습니다.

직접 해보기

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: 모드에 따라 제품 정렬
	// 모드가 "price"인 경우 ByPrice 타입 사용
	// 모드가 "quantity"인 경우 ByQuantity 타입 사용
	// 적절한 타입과 함께 sort.Sort() 사용

	// TODO: 각 제품을 다음 형식으로 출력:
	// [Name]: $[Price] (x[Quantity])
	// 가격 포맷팅을 위해 %.2f와 함께 fmt.Printf 사용
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨