День 18 · дополнительные материалы

День 18 — глубже

Всё здесь необязательно. Материалы на английском помечены.


Новая map внутри функции

На пятой странице запись в переданную map была видна снаружи. А если внутри функции присвоить параметру новую map?

Код для чтения · разбираем, набирать не нужно
package main

import "fmt"

func fill(counts map[string]int) {
	counts = map[string]int{}
	counts["K-417"] = 1
}

func main() {
	var counts map[string]int
	fill(counts)
	fmt.Println(len(counts))
}
Вывод · это печатает программа, набирать не нужно
0

Присваивание меняет только копию указания внутри fill: новая map создана, запись ушла в неё, а переменная counts в main по-прежнему nil. Хотите, чтобы функция создала map, — возвращайте её результатом, как totals в задании group. С append внутри функции в дне 17 было то же самое.

Как сортируются строки

slices.Sorted сравнивает строки по байтам: цифры раньше латинских заглавных, заглавные раньше строчных, латиница раньше кириллицы. Для артикулов одного вида (A-210, K-417, M-120) это обычный алфавитный порядок. Но B-10 окажется раньше B-9: сравнение идёт по символам слева, и 1 меньше 9. Поэтому номера в артикулах делают одной длины: B-009, B-010.

Срез или map: подробно

Что нужно Срез map
порядок значений: строки ввода, очередь заказов хранит порядок порядка нет
найти значение по артикулу перебор всех элементов сразу, по ключу
одно и то же значение несколько раз хранит все повторы один ключ — одна пара
номер элемента есть нет
сравнить через == нельзя, только с nil нельзя, только с nil; целиком — maps.Equal
печать в одном и том же порядке как лежит через отсортированные ключи
объявить через var и сразу писать append к nil-срезу работает запись в nil-map — паника
ключ из нескольких частей: склад и ячейка — пока соединяйте в строку: "A-3"

Map в официальных материалах (англ.)

Как map устроена внутри (англ.)

Мини-опыты

Попробуйте сейчас: clear и len.

Цель: увидеть разницу между «очистить map» и «создать новую».

1. В черновике создайте map из трёх пар, передайте её в функцию, которая вызывает встроенную clear(m), и напечатайте len в main после вызова.

2. Замените в функции clear(m) на m = map[string]int{} и снова напечатайте len в main.

▶ Выполните
cd ~/gocourse/day18/scratch
go run .

Готово, когда: вы можете объяснить по картинке со страницы 5 и по разделу «Новая map внутри функции», почему два запуска напечатали разную длину.

Попробуйте сейчас: map срезов.

Цель: сгруппировать номера строк по артикулу.

1. Значением map может быть срез: map[string][]int. Прочитайте со ввода артикулы и для каждого запишите номера строк, где он встретился: lines[sku] = append(lines[sku], n). Нулевое значение для среза — nil, и append к нему работает — так же, как ++ к нулю у счётчика.

2. Напечатайте по возрастанию артикула: K-417 [1 3].

▶ Выполните
printf 'K-417\nM-120\nK-417\n' | go run .

Готово, когда: у каждого артикула напечатаны все его номера строк в порядке ввода.