В Go для сортировки пользовательских типов данных используется пакет sort
. Для сортировки массива (среза) структур по строковому полю Name существует несколько способов:
type Person struct {
Name string
Age int
}
people := []Person{
{"John", 30},
{"Alice", 25},
{"Bob", 35},
}
sort.Slice(people, func(i, j int) bool {
return people[i].Name < people[j].Name
})
Преимущества:
Для более сложных случаев или многократной сортировки:
type ByName []Person
func (a ByName) Len() int { return len(a) }
func (a ByName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByName) Less(i, j int) bool { return a[i].Name < a[j].Name }
func main() {
people := []Person{
{"John", 30},
{"Alice", 25},
{"Bob", 35},
}
sort.Sort(ByName(people))
}
Когда использовать:
Для регистронезависимой сортировки:
sort.Slice(people, func(i, j int) bool {
return strings.ToLower(people[i].Name) < strings.ToLower(people[j].Name)
})
Если нужно сохранить порядок равных элементов:
sort.SliceStable(people, func(i, j int) bool {
return people[i].Name < people[j].Name
})
package main
import (
"fmt"
"sort"
)
type Person struct {
Name string
Age int
}
func main() {
people := []Person{
{"John", 30},
{"Alice", 25},
{"Bob", 35},
{"alice", 28}, // Для демонстрации регистра
}
// Сортировка с учетом регистра
sort.Slice(people, func(i, j int) bool {
return strings.ToLower(people[i].Name) < strings.ToLower(people[j].Name)
})
fmt.Println(people)
// Output: [{alice 28} {Alice 25} {Bob 35} {John 30}]
}
type PersonWithKey struct {
Person Person
Key string // ToLower или другие преобразования
}
// Создать срез с предварительно вычисленными ключами
// Отсортировать его
// Вернуть оригинальные структуры
var people []Person
var nameKeys []string
func prepareSort() {
nameKeys = make([]string, len(people))
for i := range people {
nameKeys[i] = strings.ToLower(people[i].Name)
}
}
func sortByName() {
sort.Slice(people, func(i, j int) bool {
return nameKeys[i] < nameKeys[j]
})
}
Если имена совпадают, можно добавить второе поле для сортировки:
sort.Slice(people, func(i, j int) bool {
if people[i].Name == people[j].Name {
return people[i].Age < people[j].Age
}
return people[i].Name < people[j].Name
})
Пример теста для проверки корректности сортировки:
func TestSortByName(t *testing.T) {
people := []Person{
{"John", 30},
{"Alice", 25},
{"Bob", 35},
}
expected := []Person{
{"Alice", 25},
{"Bob", 35},
{"John", 30},
}
sort.Slice(people, func(i, j int) bool {
return people[i].Name < people[j].Name
})
if !reflect.DeepEqual(people, expected) {
t.Errorf("Sort failed, got %v, want %v", people, expected)
}
}
в Go существует несколько способов сортировки среза структур по строковому полю. Наиболее современный и удобный - использование sort.Slice
с функцией сравнения. Для более сложных случаев или многократного использования следует реализовать sort.Interface
. Всегда учитывайте необходимость регистронезависимой сортировки и возможность сортировки по дополнительным полям при равенстве основных.