Spec-Zone.ru › Go

Пакет sort

  • import "sort"
  • Обзор
  • Указатель
  • Примеры

Обзор

Пакет sort предоставляет примитивы для сортировки срезов и пользовательских коллекций.

Пример

Код:

package sort_test

import (
    "fmt"
    "sort"
)

type Person struct {
    Name string
    Age  int
}

func (p Person) String() string {
    return fmt.Sprintf("%s: %d", p.Name, p.Age)
}

// ByAge implements sort.Interface for []Person based on
// the Age field.
type ByAge []Person

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

func Example() {
    people := []Person{
        {"Bob", 31},
        {"John", 42},
        {"Michael", 17},
        {"Jenny", 26},
    }

    fmt.Println(people)
    // There are two ways to sort a slice. First, one can define
    // a set of methods for the slice type, as with ByAge, and
    // call sort.Sort. In this first example we use that technique.
    sort.Sort(ByAge(people))
    fmt.Println(people)

    // The other way is to use sort.Slice with a custom Less
    // function, which can be provided as a closure. In this
    // case no methods are needed. (And if they exist, they
    // are ignored.) Here we re-sort in reverse order: compare
    // the closure with ByAge.Less.
    sort.Slice(people, func(i, j int) bool {
        return people[i].Age > people[j].Age
    })
    fmt.Println(people)

    // Output:
    // [Bob: 31 John: 42 Michael: 17 Jenny: 26]
    // [Michael: 17 Jenny: 26 Bob: 31 John: 42]
    // [John: 42 Bob: 31 Jenny: 26 Michael: 17]
}

Пример (SortKeys)

Example_sortKeys демонстрирует способ сортировки структурного типа с использованием программируемых критериев сортировки.

Код:

package sort_test

import (
    "fmt"
    "sort"
)

// A couple of type definitions to make the units clear.
type earthMass float64
type au float64

// A Planet defines the properties of a solar system object.
type Planet struct {
    name     string
    mass     earthMass
    distance au
}

// By is the type of a "less" function that defines the ordering of its Planet arguments.
type By func(p1, p2 *Planet) bool

// Sort is a method on the function type, By, that sorts the argument slice according to the function.
func (by By) Sort(planets []Planet) {
    ps := &planetSorter{
        planets: planets,
        by:      by, // The Sort method's receiver is the function (closure) that defines the sort order.
    }
    sort.Sort(ps)
}

// planetSorter joins a By function and a slice of Planets to be sorted.
type planetSorter struct {
    planets []Planet
    by      func(p1, p2 *Planet) bool // Closure used in the Less method.
}

// Len is part of sort.Interface.
func (s *planetSorter) Len() int {
    return len(s.planets)
}

// Swap is part of sort.Interface.
func (s *planetSorter) Swap(i, j int) {
    s.planets[i], s.planets[j] = s.planets[j], s.planets[i]
}

// Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter.
func (s *planetSorter) Less(i, j int) bool {
    return s.by(&s.planets[i], &s.planets[j])
}

var planets = []Planet{
    {"Mercury", 0.055, 0.4},
    {"Venus", 0.815, 0.7},
    {"Earth", 1.0, 1.0},
    {"Mars", 0.107, 1.5},
}

// Example_sortKeys demonstrates a technique for sorting a struct type using programmable sort criteria.
func Example_sortKeys() {
    // Closures that order the Planet structure.
    name := func(p1, p2 *Planet) bool {
        return p1.name < p2.name
    }
    mass := func(p1, p2 *Planet) bool {
        return p1.mass < p2.mass
    }
    distance := func(p1, p2 *Planet) bool {
        return p1.distance < p2.distance
    }
    decreasingDistance := func(p1, p2 *Planet) bool {
        return distance(p2, p1)
    }

    // Sort the planets by the various criteria.
    By(name).Sort(planets)
    fmt.Println("By name:", planets)

    By(mass).Sort(planets)
    fmt.Println("By mass:", planets)

    By(distance).Sort(planets)
    fmt.Println("By distance:", planets)

    By(decreasingDistance).Sort(planets)
    fmt.Println("By decreasing distance:", planets)

    // Output: By name: [{Earth 1 1} {Mars 0.107 1.5} {Mercury 0.055 0.4} {Venus 0.815 0.7}]
    // By mass: [{Mercury 0.055 0.4} {Mars 0.107 1.5} {Venus 0.815 0.7} {Earth 1 1}]
    // By distance: [{Mercury 0.055 0.4} {Venus 0.815 0.7} {Earth 1 1} {Mars 0.107 1.5}]
    // By decreasing distance: [{Mars 0.107 1.5} {Earth 1 1} {Venus 0.815 0.7} {Mercury 0.055 0.4}]
}

Пример (SortMultiKeys)

Example_sortMultiKeys демонстрирует способ сортировки структурного типа с использованием разных наборов нескольких полей для сравнения. Мы объединяем цепочкой функции "Less", каждая из которых сравнивает одно поле.

Код:

package sort_test

import (
    "fmt"
    "sort"
)

// A Change is a record of source code changes, recording user, language, and delta size.
type Change struct {
    user     string
    language string
    lines    int
}

type lessFunc func(p1, p2 *Change) bool

// multiSorter implements the Sort interface, sorting the changes within.
type multiSorter struct {
    changes []Change
    less    []lessFunc
}

// Sort sorts the argument slice according to the less functions passed to OrderedBy.
func (ms *multiSorter) Sort(changes []Change) {
    ms.changes = changes
    sort.Sort(ms)
}

// OrderedBy returns a Sorter that sorts using the less functions, in order.
// Call its Sort method to sort the data.
func OrderedBy(less ...lessFunc) *multiSorter {
    return &multiSorter{
        less: less,
    }
}

// Len is part of sort.Interface.
func (ms *multiSorter) Len() int {
    return len(ms.changes)
}

// Swap is part of sort.Interface.
func (ms *multiSorter) Swap(i, j int) {
    ms.changes[i], ms.changes[j] = ms.changes[j], ms.changes[i]
}

// Less is part of sort.Interface. It is implemented by looping along the
// less functions until it finds a comparison that discriminates between
// the two items (one is less than the other). Note that it can call the
// less functions twice per call. We could change the functions to return
// -1, 0, 1 and reduce the number of calls for greater efficiency: an
// exercise for the reader.
func (ms *multiSorter) Less(i, j int) bool {
    p, q := &ms.changes[i], &ms.changes[j]
    // Try all but the last comparison.
    var k int
    for k = 0; k < len(ms.less)-1; k++ {
        less := ms.less[k]
        switch {
        case less(p, q):
            // p < q, so we have a decision.
            return true
        case less(q, p):
            // p > q, so we have a decision.
            return false
        }
        // p == q; try the next comparison.
    }
    // All comparisons to here said "equal", so just return whatever
    // the final comparison reports.
    return ms.less[k](p, q)
}

var changes = []Change{
    {"gri", "Go", 100},
    {"ken", "C", 150},
    {"glenda", "Go", 200},
    {"rsc", "Go", 200},
    {"r", "Go", 100},
    {"ken", "Go", 200},
    {"dmr", "C", 100},
    {"r", "C", 150},
    {"gri", "Smalltalk", 80},
}

// Example_sortMultiKeys demonstrates a technique for sorting a struct type using different
// sets of multiple fields in the comparison. We chain together "Less" functions, each of
// which compares a single field.
func Example_sortMultiKeys() {
    // Closures that order the Change structure.
    user := func(c1, c2 *Change) bool {
        return c1.user < c2.user
    }
    language := func(c1, c2 *Change) bool {
        return c1.language < c2.language
    }
    increasingLines := func(c1, c2 *Change) bool {
        return c1.lines < c2.lines
    }
    decreasingLines := func(c1, c2 *Change) bool {
        return c1.lines > c2.lines // Note: > orders downwards.
    }

    // Simple use: Sort by user.
    OrderedBy(user).Sort(changes)
    fmt.Println("By user:", changes)

    // More examples.
    OrderedBy(user, increasingLines).Sort(changes)
    fmt.Println("By user,<lines:", changes)

    OrderedBy(user, decreasingLines).Sort(changes)
    fmt.Println("By user,>lines:", changes)

    OrderedBy(language, increasingLines).Sort(changes)
    fmt.Println("By language,<lines:", changes)

    OrderedBy(language, increasingLines, user).Sort(changes)
    fmt.Println("By language,<lines,user:", changes)

    // Output:
    // By user: [{dmr C 100} {glenda Go 200} {gri Go 100} {gri Smalltalk 80} {ken C 150} {ken Go 200} {r Go 100} {r C 150} {rsc Go 200}]
    // By user,<lines: [{dmr C 100} {glenda Go 200} {gri Smalltalk 80} {gri Go 100} {ken C 150} {ken Go 200} {r Go 100} {r C 150} {rsc Go 200}]
    // By user,>lines: [{dmr C 100} {glenda Go 200} {gri Go 100} {gri Smalltalk 80} {ken Go 200} {ken C 150} {r C 150} {r Go 100} {rsc Go 200}]
    // By language,<lines: [{dmr C 100} {ken C 150} {r C 150} {gri Go 100} {r Go 100} {glenda Go 200} {ken Go 200} {rsc Go 200} {gri Smalltalk 80}]
    // By language,<lines,user: [{dmr C 100} {ken C 150} {r C 150} {gri Go 100} {r Go 100} {glenda Go 200} {ken Go 200} {rsc Go 200} {gri Smalltalk 80}]

}

Пример (SortWrapper)

Код:

package sort_test

import (
    "fmt"
    "sort"
)

type Grams int

func (g Grams) String() string { return fmt.Sprintf("%dg", int(g)) }

type Organ struct {
    Name   string
    Weight Grams
}

type Organs []*Organ

func (s Organs) Len() int      { return len(s) }
func (s Organs) Swap(i, j int) { s[i], s[j] = s[j], s[i] }

// ByName implements sort.Interface by providing Less and using the Len and
// Swap methods of the embedded Organs value.
type ByName struct{ Organs }

func (s ByName) Less(i, j int) bool { return s.Organs[i].Name < s.Organs[j].Name }

// ByWeight implements sort.Interface by providing Less and using the Len and
// Swap methods of the embedded Organs value.
type ByWeight struct{ Organs }

func (s ByWeight) Less(i, j int) bool { return s.Organs[i].Weight < s.Organs[j].Weight }

func Example_sortWrapper() {
    s := []*Organ{
        {"brain", 1340},
        {"heart", 290},
        {"liver", 1494},
        {"pancreas", 131},
        {"prostate", 62},
        {"spleen", 162},
    }

    sort.Sort(ByWeight{s})
    fmt.Println("Organs by weight:")
    printOrgans(s)

    sort.Sort(ByName{s})
    fmt.Println("Organs by name:")
    printOrgans(s)

    // Output:
    // Organs by weight:
    // prostate (62g)
    // pancreas (131g)
    // spleen   (162g)
    // heart    (290g)
    // brain    (1340g)
    // liver    (1494g)
    // Organs by name:
    // brain    (1340g)
    // heart    (290g)
    // liver    (1494g)
    // pancreas (131g)
    // prostate (62g)
    // spleen   (162g)
}

func printOrgans(s []*Organ) {
    for _, o := range s {
        fmt.Printf("%-8s (%v)\n", o.Name, o.Weight)
    }
}

Указатель

  • func Find(n int, cmp func(int) int) (i int, found bool)
  • func Float64s(x []float64)
  • func Float64sAreSorted(x []float64) bool
  • func Ints(x []int)
  • func IntsAreSorted(x []int) bool
  • func IsSorted(data Interface) bool
  • func Search(n int, f func(int) bool) int
  • func SearchFloat64s(a []float64, x float64) int
  • func SearchInts(a []int, x int) int
  • func SearchStrings(a []string, x string) int
  • func Slice(x any, less func(i, j int) bool)
  • func SliceIsSorted(x any, less func(i, j int) bool) bool
  • func SliceStable(x any, less func(i, j int) bool)
  • func Sort(data Interface)
  • func Stable(data Interface)
  • func Strings(x []string)
  • func StringsAreSorted(x []string) bool
  • type Float64Slice
  • func (x Float64Slice) Len() int
  • func (x Float64Slice) Less(i, j int) bool
  • func (p Float64Slice) Search(x float64) int
  • func (x Float64Slice) Sort()
  • func (x Float64Slice) Swap(i, j int)
  • type IntSlice
  • func (x IntSlice) Len() int
  • func (x IntSlice) Less(i, j int) bool
  • func (p IntSlice) Search(x int) int
  • func (x IntSlice) Sort()
  • func (x IntSlice) Swap(i, j int)
  • type Interface
  • func Reverse(data Interface) Interface
  • type StringSlice
  • func (x StringSlice) Len() int
  • func (x StringSlice) Less(i, j int) bool
  • func (p StringSlice) Search(x string) int
  • func (x StringSlice) Sort()
  • func (x StringSlice) Swap(i, j int)

Примеры

Пакет
Find
Float64s
Float64sAreSorted
Ints
IntsAreSorted
Reverse
Search
SearchFloat64s
SearchInts
SearchStrings
Search (DescendingOrder)
Slice
SliceIsSorted
SliceStable
Strings
Пакет (SortKeys)
Пакет (SortMultiKeys)
Пакет (SortWrapper)

Файлы пакета

search.go slice.go sort.go zsortfunc.go zsortinterface.go

func Find 1.19

func Find(n int, cmp func(int) int) (i int, found bool)

Find использует бинарный поиск, чтобы найти и вернуть наименьший индекс i в [0, n), для которого cmp(i) <= 0. Если такого индекса i нет, Find возвращает i = n. Результат found равен true, если i < n и cmp(i) == 0. Find вызывает cmp(i) только для i из диапазона [0, n).

Для выполнения бинарного поиска требуется, чтобы cmp(i) > 0 для начального префикса диапазона, cmp(i) == 0 для средней части и cmp(i) < 0 для конечного суффикса диапазона. (Каждая из этих частей может быть пустой.) Обычно это условие обеспечивается интерпретацией cmp(i) как сравнения искомого целевого значения t с элементом i в базовой индексируемой структуре данных x, возвращающего <0, 0 и >0, когда t < x[i], t == x[i] и t > x[i] соответственно.

Например, чтобы найти определённую строку в отсортированном списке строк с произвольным доступом:

i, found := sort.Find(x.Len(), func(i int) int {
    return strings.Compare(target, x.At(i))
})
if found {
    fmt.Printf("found %s at entry %d\n", target, i)
} else {
    fmt.Printf("%s not found, would insert at %d", target, i)
}

Пример

В этом примере показан поиск строки в списке, отсортированном по возрастанию.

Код:

a := []string{"apple", "banana", "lemon", "mango", "pear", "strawberry"}

for _, x := range []string{"banana", "orange"} {
    i, found := sort.Find(len(a), func(i int) int {
        return strings.Compare(x, a[i])
    })
    if found {
        fmt.Printf("found %s at index %d\n", x, i)
    } else {
        fmt.Printf("%s not found, would insert at %d\n", x, i)
    }
}

Результат:

found banana at index 1
orange not found, would insert at 4

func Float64s

func Float64s(x []float64)

Float64s сортирует срез значений float64 по возрастанию. Значения «не число» (NaN) располагаются перед остальными значениями.

Примечание: начиная с Go 1.22 эта функция просто вызывает slices.Sort.

Пример

Код:

s := []float64{5.2, -1.3, 0.7, -3.8, 2.6} // unsorted
sort.Float64s(s)
fmt.Println(s)

s = []float64{math.Inf(1), math.NaN(), math.Inf(-1), 0.0} // unsorted
sort.Float64s(s)
fmt.Println(s)

Результат:

[-3.8 -1.3 0.7 2.6 5.2]
[NaN -Inf 0 +Inf]

func Float64sAreSorted

func Float64sAreSorted(x []float64) bool

Float64sAreSorted сообщает, отсортирован ли срез x по возрастанию, причём значения «не число» (NaN) располагаются перед всеми остальными значениями.

Примечание: начиная с Go 1.22 эта функция просто вызывает slices.IsSorted.

Пример

Код:

s := []float64{0.7, 1.3, 2.6, 3.8, 5.2} // sorted ascending
fmt.Println(sort.Float64sAreSorted(s))

s = []float64{5.2, 3.8, 2.6, 1.3, 0.7} // sorted descending
fmt.Println(sort.Float64sAreSorted(s))

s = []float64{5.2, 1.3, 0.7, 3.8, 2.6} // unsorted
fmt.Println(sort.Float64sAreSorted(s))

Результат:

true
false
false

func Ints

func Ints(x []int)

Ints сортирует срез значений int по возрастанию.

Примечание: начиная с Go 1.22 эта функция просто вызывает slices.Sort.

Пример

Код:

s := []int{5, 2, 6, 3, 1, 4} // unsorted
sort.Ints(s)
fmt.Println(s)

Результат:

[1 2 3 4 5 6]

func IntsAreSorted

func IntsAreSorted(x []int) bool

IntsAreSorted сообщает, отсортирован ли срез x по возрастанию.

Примечание: начиная с Go 1.22 эта функция просто вызывает slices.IsSorted.

Пример

Код:

s := []int{1, 2, 3, 4, 5, 6} // sorted ascending
fmt.Println(sort.IntsAreSorted(s))

s = []int{6, 5, 4, 3, 2, 1} // sorted descending
fmt.Println(sort.IntsAreSorted(s))

s = []int{3, 2, 4, 1, 5} // unsorted
fmt.Println(sort.IntsAreSorted(s))

Результат:

true
false
false

func IsSorted

func IsSorted(data Interface) bool

IsSorted сообщает, отсортированы ли данные.

Примечание: во многих ситуациях новая функция slices.IsSortedFunc удобнее в использовании и работает быстрее.

func Search

func Search(n int, f func(int) bool) int

Search использует бинарный поиск, чтобы найти и вернуть наименьший индекс i в [0, n), для которого f(i) равно true, при условии, что в диапазоне [0, n) из f(i) == true следует f(i+1) == true. Иными словами, Search требует, чтобы f возвращала false для некоторого (возможно, пустого) префикса входного диапазона [0, n), а затем true для оставшейся (возможно, пустой) части; Search возвращает индекс первого значения true. Если такого индекса нет, Search возвращает n. (Обратите внимание: значение «не найдено» — не -1, как, например, в strings.Index.) Search вызывает f(i) только для i из диапазона [0, n).

Обычно Search используют, чтобы найти индекс i значения x в отсортированной индексируемой структуре данных, например массиве или срезе. В этом случае аргумент f, обычно замыкание, захватывает искомое значение и сведения о том, как индексируется и упорядочивается структура данных.

Например, если срез data отсортирован по возрастанию, вызов Search(len(data), func(i int) bool { return data[i] >= 23 }) возвращает наименьший индекс i, для которого data[i] >= 23. Если вызывающему коду нужно выяснить, содержится ли в срезе значение 23, он должен отдельно проверить data[i] == 23.

Для поиска в данных, отсортированных по убыванию, вместо оператора >= следует использовать оператор <=.

В завершение приведённого выше примера следующий код пытается найти значение x в целочисленном срезе data, отсортированном по возрастанию:

x := 23
i := sort.Search(len(data), func(i int) bool { return data[i] >= x })
if i < len(data) && data[i] == x {
	// x is present at data[i]
} else {
	// x is not present in data,
	// but i is the index where it would be inserted.
}

В качестве более забавного примера эта программа угадывает ваше число:

func GuessingGame() {
	var s string
	fmt.Printf("Pick an integer from 0 to 100.\n")
	answer := sort.Search(100, func(i int) bool {
		fmt.Printf("Is your number <= %d? ", i)
		fmt.Scanf("%s", &s)
		return s != "" && s[0] == 'y'
	})
	fmt.Printf("Your number is %d.\n", answer)
}

Пример

В этом примере показан поиск в списке, отсортированном по возрастанию.

Код:

a := []int{1, 3, 6, 10, 15, 21, 28, 36, 45, 55}
x := 6

i := sort.Search(len(a), func(i int) bool { return a[i] >= x })
if i < len(a) && a[i] == x {
    fmt.Printf("found %d at index %d in %v\n", x, i, a)
} else {
    fmt.Printf("%d not found in %v\n", x, a)
}

Результат:

found 6 at index 2 in [1 3 6 10 15 21 28 36 45 55]

Пример (DescendingOrder)

В этом примере показан поиск в списке, отсортированном по убыванию. Подход такой же, как при поиске в списке, отсортированном по возрастанию, но условие инвертировано.

Код:

a := []int{55, 45, 36, 28, 21, 15, 10, 6, 3, 1}
x := 6

i := sort.Search(len(a), func(i int) bool { return a[i] <= x })
if i < len(a) && a[i] == x {
    fmt.Printf("found %d at index %d in %v\n", x, i, a)
} else {
    fmt.Printf("%d not found in %v\n", x, a)
}

Результат:

found 6 at index 7 in [55 45 36 28 21 15 10 6 3 1]

func SearchFloat64s

func SearchFloat64s(a []float64, x float64) int

SearchFloat64s выполняет поиск x в отсортированном срезе значений float64 и возвращает индекс, как описано в Search. Возвращаемое значение — это индекс, куда следует вставить x, если его нет в срезе (это может быть len(a)). Срез должен быть отсортирован по возрастанию.

Пример

В этом примере показан поиск значения float64 в списке, отсортированном по возрастанию.

Код:

a := []float64{1.0, 2.0, 3.3, 4.6, 6.1, 7.2, 8.0}

x := 2.0
i := sort.SearchFloat64s(a, x)
fmt.Printf("found %g at index %d in %v\n", x, i, a)

x = 0.5
i = sort.SearchFloat64s(a, x)
fmt.Printf("%g not found, can be inserted at index %d in %v\n", x, i, a)

Результат:

found 2 at index 1 in [1 2 3.3 4.6 6.1 7.2 8]
0.5 not found, can be inserted at index 0 in [1 2 3.3 4.6 6.1 7.2 8]

func SearchInts

func SearchInts(a []int, x int) int

SearchInts выполняет поиск x в отсортированном срезе значений int и возвращает индекс, как описано в Search. Возвращаемое значение — это индекс, куда следует вставить x, если его нет в срезе (это может быть len(a)). Срез должен быть отсортирован по возрастанию.

Пример

В этом примере показан поиск значения int в списке, отсортированном по возрастанию.

Код:

a := []int{1, 2, 3, 4, 6, 7, 8}

x := 2
i := sort.SearchInts(a, x)
fmt.Printf("found %d at index %d in %v\n", x, i, a)

x = 5
i = sort.SearchInts(a, x)
fmt.Printf("%d not found, can be inserted at index %d in %v\n", x, i, a)

Результат:

found 2 at index 1 in [1 2 3 4 6 7 8]
5 not found, can be inserted at index 4 in [1 2 3 4 6 7 8]

func SearchStrings

func SearchStrings(a []string, x string) int

SearchStrings выполняет поиск x в отсортированном срезе строк и возвращает индекс, как описано в Search. Возвращаемое значение — это индекс, куда следует вставить x, если его нет в срезе (это может быть len(a)). Срез должен быть отсортирован по возрастанию.

Пример

В этом примере показан поиск строки в списке, отсортированном по возрастанию.

Код:

a := []string{"apple", "banana", "cherry", "date", "fig", "grape"}

x := "banana"
i := sort.SearchStrings(a, x)
fmt.Printf("found %s at index %d in %v\n", x, i, a)

x = "coconut"
i = sort.SearchStrings(a, x)
fmt.Printf("%s not found, can be inserted at index %d in %v\n", x, i, a)

Результат:

found banana at index 1 in [apple banana cherry date fig grape]
coconut not found, can be inserted at index 3 in [apple banana cherry date fig grape]

func Slice 1.8

func Slice(x any, less func(i, j int) bool)

Slice сортирует срез x с помощью предоставленной функции less. Вызывает панику, если x не является срезом.

Стабильность сортировки не гарантируется: равные элементы могут поменяться местами относительно исходного порядка. Для стабильной сортировки используйте SliceStable.

Функция less должна удовлетворять тем же требованиям, что и метод Less типа Interface.

Примечание: во многих ситуациях новая функция slices.SortFunc удобнее в использовании и работает быстрее.

Пример

Код:

people := []struct {
    Name string
    Age  int
}{
    {"Gopher", 7},
    {"Alice", 55},
    {"Vera", 24},
    {"Bob", 75},
}
sort.Slice(people, func(i, j int) bool { return people[i].Name < people[j].Name })
fmt.Println("By name:", people)

sort.Slice(people, func(i, j int) bool { return people[i].Age < people[j].Age })
fmt.Println("By age:", people)

Результат:

By name: [{Alice 55} {Bob 75} {Gopher 7} {Vera 24}]
By age: [{Gopher 7} {Vera 24} {Alice 55} {Bob 75}]

func SliceIsSorted 1.8

func SliceIsSorted(x any, less func(i, j int) bool) bool

SliceIsSorted сообщает, отсортирован ли срез x согласно предоставленной функции less. Вызывает панику, если x не является срезом.

Примечание: во многих ситуациях новая функция slices.IsSortedFunc удобнее в использовании и работает быстрее.

Пример

Код:

numbers := []int{1, 2, 3, 4, 5, 6}

isSortedAsc := sort.SliceIsSorted(numbers, func(i, j int) bool {
    return numbers[i] < numbers[j]
})
fmt.Printf("%v sorted ascending: %t\n", numbers, isSortedAsc)

numbersDesc := []int{6, 5, 4, 3, 2, 1}

isSortedDesc := sort.SliceIsSorted(numbersDesc, func(i, j int) bool {
    return numbersDesc[i] > numbersDesc[j]
})
fmt.Printf("%v sorted descending: %t\n", numbers, isSortedDesc)

unsortedNumbers := []int{1, 3, 2, 4, 5}

isSortedUnsorted := sort.SliceIsSorted(unsortedNumbers, func(i, j int) bool {
    return unsortedNumbers[i] < unsortedNumbers[j]
})
fmt.Printf("%v unsorted slice sorted: %t\n", unsortedNumbers, isSortedUnsorted)

Результат:

[1 2 3 4 5 6] sorted ascending: true
[1 2 3 4 5 6] sorted descending: true
[1 3 2 4 5] unsorted slice sorted: false

func SliceStable 1.8

func SliceStable(x any, less func(i, j int) bool)

SliceStable сортирует срез x с помощью предоставленной функции less, сохраняя исходный порядок равных элементов. Вызывает панику, если x не является срезом.

Функция less должна удовлетворять тем же требованиям, что и метод Less типа Interface.

Примечание: во многих ситуациях новая функция slices.SortStableFunc удобнее в использовании и работает быстрее.

Пример

Код:

people := []struct {
    Name string
    Age  int
}{
    {"Alice", 25},
    {"Elizabeth", 75},
    {"Alice", 75},
    {"Bob", 75},
    {"Alice", 75},
    {"Bob", 25},
    {"Colin", 25},
    {"Elizabeth", 25},
}

// Sort by name, preserving original order
sort.SliceStable(people, func(i, j int) bool { return people[i].Name < people[j].Name })
fmt.Println("By name:", people)

// Sort by age preserving name order
sort.SliceStable(people, func(i, j int) bool { return people[i].Age < people[j].Age })
fmt.Println("By age,name:", people)

Результат:

By name: [{Alice 25} {Alice 75} {Alice 75} {Bob 75} {Bob 25} {Colin 25} {Elizabeth 75} {Elizabeth 25}]
By age,name: [{Alice 25} {Bob 25} {Colin 25} {Elizabeth 25} {Alice 75} {Alice 75} {Bob 75} {Elizabeth 75}]

func Sort

func Sort(data Interface)

Sort сортирует данные по возрастанию согласно методу Less. Функция один раз вызывает data.Len, чтобы определить n, и O(n*log(n)) раз вызывает data.Less и data.Swap. Стабильность сортировки не гарантируется.

Примечание: во многих ситуациях новая функция slices.SortFunc удобнее в использовании и работает быстрее.

func Stable 1.2

func Stable(data Interface)

Stable сортирует данные по возрастанию согласно методу Less, сохраняя исходный порядок равных элементов.

Функция один раз вызывает data.Len, чтобы определить n, O(n*log(n)) раз вызывает data.Less и O(n*log(n)*log(n)) раз вызывает data.Swap.

Примечание: во многих ситуациях новая функция slices.SortStableFunc удобнее в использовании и работает быстрее.

func Strings

func Strings(x []string)

Strings сортирует срез строк по возрастанию.

Примечание: начиная с Go 1.22 эта функция просто вызывает slices.Sort.

Пример

Код:

s := []string{"Go", "Bravo", "Gopher", "Alpha", "Grin", "Delta"}
sort.Strings(s)
fmt.Println(s)

Результат:

[Alpha Bravo Delta Go Gopher Grin]

func StringsAreSorted

func StringsAreSorted(x []string) bool

StringsAreSorted сообщает, отсортирован ли срез x по возрастанию.

Примечание: начиная с Go 1.22 эта функция просто вызывает slices.IsSorted.

type Float64Slice

Float64Slice реализует Interface для []float64, выполняя сортировку по возрастанию и располагая значения «не число» (NaN) перед остальными значениями.

type Float64Slice []float64

func (Float64Slice) Len

func (x Float64Slice) Len() int

func (Float64Slice) Less

func (x Float64Slice) Less(i, j int) bool

Less сообщает, следует ли расположить x[i] перед x[j], как того требует интерфейс sort.Interface. Обратите внимание: сравнение чисел с плавающей точкой само по себе не является транзитивным отношением: для значений «не число» (NaN) оно не задаёт согласованного порядка. Эта реализация Less располагает значения NaN перед всеми остальными, используя:

x[i] < x[j] || (math.IsNaN(x[i]) && !math.IsNaN(x[j]))

func (Float64Slice) Search

func (p Float64Slice) Search(x float64) int

Search возвращает результат применения SearchFloat64s к получателю и x.

func (Float64Slice) Sort

func (x Float64Slice) Sort()

Sort — вспомогательный метод: x.Sort() вызывает Sort(x).

func (Float64Slice) Swap

func (x Float64Slice) Swap(i, j int)

type IntSlice

IntSlice связывает методы Interface со []int, выполняя сортировку по возрастанию.

type IntSlice []int

func (IntSlice) Len

func (x IntSlice) Len() int

func (IntSlice) Less

func (x IntSlice) Less(i, j int) bool

func (IntSlice) Search

func (p IntSlice) Search(x int) int

Search возвращает результат применения SearchInts к получателю и x.

func (IntSlice) Sort

func (x IntSlice) Sort()

Sort — вспомогательный метод: x.Sort() вызывает Sort(x).

func (IntSlice) Swap

func (x IntSlice) Swap(i, j int)

type Interface

Реализацию Interface можно сортировать с помощью функций этого пакета. Методы обращаются к элементам базовой коллекции по целочисленному индексу.

type Interface interface {
    // Len is the number of elements in the collection.
    Len() int

    // Less reports whether the element with index i
    // must sort before the element with index j.
    //
    // If both Less(i, j) and Less(j, i) are false,
    // then the elements at index i and j are considered equal.
    // Sort may place equal elements in any order in the final result,
    // while Stable preserves the original input order of equal elements.
    //
    // Less must describe a [Strict Weak Ordering]. For example:
    //  - if both Less(i, j) and Less(j, k) are true, then Less(i, k) must be true as well.
    //  - if both Less(i, j) and Less(j, k) are false, then Less(i, k) must be false as well.
    //
    // Note that floating-point comparison (the < operator on float32 or float64 values)
    // is not a strict weak ordering when not-a-number (NaN) values are involved.
    // See Float64Slice.Less for a correct implementation for floating-point values.
    //
    // [Strict Weak Ordering]: https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings
    Less(i, j int) bool

    // Swap swaps the elements with indexes i and j.
    Swap(i, j int)
}

func Reverse 1.1

func Reverse(data Interface) Interface

Reverse возвращает обратный порядок элементов data.

Пример

Код:

s := []int{5, 2, 6, 3, 1, 4} // unsorted
sort.Sort(sort.Reverse(sort.IntSlice(s)))
fmt.Println(s)

Результат:

[6 5 4 3 2 1]

type StringSlice

StringSlice связывает методы Interface со []string, выполняя сортировку по возрастанию.

type StringSlice []string

func (StringSlice) Len

func (x StringSlice) Len() int

func (StringSlice) Less

func (x StringSlice) Less(i, j int) bool

func (StringSlice) Search

func (p StringSlice) Search(x string) int

Search возвращает результат применения SearchStrings к получателю и x.

func (StringSlice) Sort

func (x StringSlice) Sort()

Sort — вспомогательный метод: x.Sort() вызывает Sort(x).

func (StringSlice) Swap

func (x StringSlice) Swap(i, j int)

© Google, Inc.
Licensed under the Creative Commons Attribution License 3.0.
http://golang.org/pkg/sort/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API