Готовые функции: пакет slices
Сортировку, поиск и максимум в блоке 2 писали циклом. Для срезов всё это уже есть в стандартном пакете slices. Подключается он как strings в дне 04: строкой в import.
Шесть функций на каждый день
Ситуация. Остатки пяти ячеек: есть ли ячейка с 60, где лежит 12, сколько в самой полной и пустой, все остатки по возрастанию.
package main
import (
"fmt"
"slices"
)
func main() {
stock := []int{25, 3, 60, 12, 40}
fmt.Println(slices.Contains(stock, 60), slices.Contains(stock, 61))
fmt.Println(slices.Index(stock, 12), slices.Index(stock, 13))
fmt.Println(slices.Max(stock), slices.Min(stock))
slices.Sort(stock)
fmt.Println(stock)
fmt.Println(slices.Equal(stock, []int{3, 12, 25, 40, 60}))
}Что увидите.
true false
3 -1
60 3
[3 12 25 40 60]
trueКак это читать.
| Функция | Что делает |
|---|---|
slices.Contains(s, v) |
есть ли в срезе значение v |
slices.Index(s, v) |
индекс первого v или -1, если его нет |
slices.Max(s), slices.Min(s) |
наибольший и наименьший элемент |
slices.Sort(s) |
сортирует сам срез по возрастанию, ничего не возвращает |
slices.Equal(a, b) |
одинаковые ли длины и элементы по порядку |
slices.Clone(s) |
копия со своим массивом — страница 3 |
Те же функции работают и со строками: срез из маленьких русских слов slices.Sort расставит по алфавиту. С заглавными и с «ё» порядок другой — строки сравниваются по байтам, разберём в дне 19. Опыт со строками — в course extra 17.
В чужом коде встретите sort.Slice и slices.SortFunc: туда передают ещё одну функцию, записанную прямо на месте. Такую запись курс разберёт позже.
Справка не выходя из терминала
stagiaire@lab:~/gocourse/day17/scratch$ go doc slices.Sort
package slices // import "slices"
func Sort[S ~[]E, E cmp.Ordered](x S)
Sort sorts a slice of any ordered type in ascending order. When sorting
floating-point numbers, NaNs are ordered before other values.
Строку с квадратными скобками после Sort пока пропускайте: она говорит, что функция принимает срез значений, которые можно сравнивать больше-меньше — чисел или строк. Главное — текст ниже: sorts a slice … in ascending order. Возвращаемого значения в заголовке нет. Сравните с go doc slices.Max:
stagiaire@lab:~/gocourse/day17/scratch$ go doc slices.Max
package slices // import "slices"
func Max[S ~[]E, E cmp.Ordered](x S) E
Max returns the maximal value in x. It panics if x is empty. For
floating-point E, Max propagates NaNs (any NaN value in x forces the output
to be NaN).
E в конце заголовка — результат, «элемент среза». И предупреждение: It panics if x is empty — на пустом срезе паникует.
Попробуйте сейчас: справка по slices.
Цель: прочитать справку по двум функциям и найти, какая из них возвращает значение.
▶ Выполнитеcd ~/gocourse/day17/scratch go doc slices.Sort go doc slices.CloneГотово, когда: вы можете сказать, что возвращает
slices.Cloneи почемуx := slices.Sort(s)не соберётся, — пунктt_doc.
Sort меняет сам срез
slices.Sort не делает копию: он переставляет элементы в том массиве, который ему дали. Внутри функции — тот же дефект, что со страницы 4:
package main
import (
"fmt"
"slices"
)
func low(stock []int) []int {
slices.Sort(stock)
return stock[:2]
}
func main() {
stock := []int{25, 3, 60, 12}
fmt.Println(low(stock))
fmt.Println(stock)
}[3 12]
[3 12 25 60]Два самых пустых остатка найдены верно, а порядок ячеек у вызывающего потерян. Нужны оба — значит, сортируют копию:
package main
import (
"fmt"
"slices"
)
func main() {
stock := []int{25, 3, 60, 12, 40}
sorted := slices.Clone(stock)
slices.Sort(sorted)
fmt.Println("по возрастанию:", sorted)
fmt.Println("по ячейкам:", stock)
fmt.Println("есть ячейка с 12:", slices.Contains(stock, 12))
fmt.Println("где 60:", slices.Index(stock, 60))
}по возрастанию: [3 12 25 40 60]
по ячейкам: [25 3 60 12 40]
есть ячейка с 12: true
где 60: 2Попробуйте сейчас: задание report — отчёт с сортировкой.
Цель: отчёт по остаткам: ниже порога — по возрастанию, наибольший остаток, все ячейки в порядке ввода.
1. Прочитайте условие — порог у вас свой:
▶ Выполнитеcd ~/gocourse/day17/report cat TASK.txt2. Допишите
main.goвместо последней строки. Честных путей два: отобрать остатки ниже порога в новый срез черезappendи отсортировать его; или сделать копиюstock, отсортировать копию и отбирать из неё. Сортировать самstockнельзя: последняя строка отчёта печатает его в порядке ввода.3. Не забудьте пустой ввод:
slices.Maxна пустом срезе паникует.4. Проверьте на примере из условия — готовая команда с вашими числами напечатана в конце
TASK.txt, — потом на вводе с пустой строкой и на пустом вводе, и закоммитьте:▶ Выполнитеprintf '5\n\n70\n1\n' | go run . printf '' | go run . gofmt -l . git add . git commit -m "report: отчёт с сортировкой"Готово, когда: пример из
TASK.txtпечатается буква в букву, пустой ввод даётЯчеек нет— пунктreport. Проверка прогонит и скрытые вводы: в разном порядке, с повторами, ровно на пороге.
Что может пойти не так
| Что видите | Что это значит | Что делать |
|---|---|---|
slices.Sort(stock) (no value) used as value |
Sort ничего не возвращает, а его результат присваивают |
отдельной строкой: slices.Sort(stock) |
panic: slices.Max: empty list |
максимум пустого среза не определён | сначала if len(stock) == 0 |
invalid operation: a == b (slice can only be compared to nil) |
срезы оператором == не сравниваются |
slices.Equal(a, b) |
undefined: slices |
пакет не подключён | "slices" в import |
| «По ячейкам» печатается по возрастанию | отсортирован сам stock |
сортировать отобранное или копию |
| порог попал в «ниже» | <= вместо < |
«ниже» — строго меньше |
Дальше: тест, который проверяет, что функция не трогает вход, — course next