Golang: Слайсы из срезов
В Go есть удобная операция слайсинг (slicing), которая используется для получения поднабора элементов из среза. С помощью конструкции [:]
можно указать диапазон элементов, создавая новый срез, который ссылается на тот же базовый массив. При этом операция не копирует данные, а лишь формирует новое «окно» на существующий массив.
Как работает слайсинг [:]
Синтаксис:
s[начало:конец]
начало
— индекс, с которого начинается срез (включительно).конец
— индекс, на котором срез заканчивается (не включительно).- Если
начало
не указано — берется0
. - Если
конец
не указан — беретсяlen(s)
.
Примеры
s := []int{10, 20, 30, 40, 50}
fmt.Println(s[:]) // => [10 20 30 40 50]
fmt.Println(s[1:4]) // => [20 30 40]
fmt.Println(s[:3]) // => [10 20 30]
fmt.Println(s[2:]) // => [30 40 50]
Отрезание элементов
Срезы позволяют легко отбросить первый или последний элемент:
s := []string{"a", "b", "c", "d"}
s = s[1:] // убираем первый элемент
fmt.Println(s) // => [b c d]
s = s[:len(s)-1] // убираем последний элемент
fmt.Println(s) // => [b c]
Вложенные срезы
Так как [:]
возвращает новый срез, можно использовать его в цепочках:
s := []int{1, 2, 3, 4, 5}
middle := s[1:4] // [2 3 4]
tail := middle[1:] // [3 4]
fmt.Println(tail) // => [3 4]
Важно: все срезы указывают на один и тот же базовый массив. Изменение элемента в одном срезе повлияет на другие.
s := []int{1, 2, 3, 4}
sub := s[1:3] // [2 3]
sub[0] = 99
fmt.Println(s) // => [1 99 3 4]
Выход за пределы
Если задать границы, выходящие за пределы длины среза, будет паника времени выполнения:
s := []int{1, 2, 3}
fmt.Println(s[1:5]) // panic: slice bounds out of range
Использование [:] для "удаления" элементов
В Go нет встроенной функции для удаления элементов из среза, но [:]
позволяет легко получить новый срез без нужных элементов.
Удаление первого элемента
s := []string{"a", "b", "c", "d"}
s = s[1:]
fmt.Println(s) // => [b c d]
Удаление последнего элемента
s := []string{"a", "b", "c", "d"}
s = s[:len(s)-1]
fmt.Println(s) // => [a b c]
Удаление диапазона элементов
Можно отбросить несколько элементов, используя append()
вместе с [:]
:
s := []string{"a", "b", "c", "d", "e"}
s = append(s[:1], s[3:]...)
fmt.Println(s) // => [a d e]
Конструкция [:]
в таких примерах не копирует данные, а создаёт новый срез с нужным диапазоном, сохраняя общую память с исходным массивом.
Кратко
Операция | Синтаксис | Результат |
---|---|---|
Весь срез | s[:] | Все элементы |
От начала до индекса n | s[:n] | Элементы с индексами 0 до n-1 |
От индекса i до конца | s[i:] | Элементы от i до конца |
Диапазон от i до j | s[i:j] | Элементы с индексами i до j-1 |
Удалить первый элемент | s[1:] | Все, кроме первого |
Удалить последний элемент | s[:len(s)-1] | Все, кроме последнего |
Задание
Реализуйте функцию GetWorkHours(schedule []int) []int
, которая принимает срез schedule
, где каждый элемент — это количество рабочих часов за день недели (с понедельника по воскресенье). Функция должна вернуть рабочие часы только за будние дни (понедельник–пятница). Если данных меньше пяти элементов, вернуть пустой срез.
Примеры
GetWorkHours([]int{8, 8, 8, 8, 6, 0, 0}) // [8 8 8 8 6]
GetWorkHours([]int{8, 8, 8, 8}) // []
GetWorkHours([]int{}) // []
Команда проекта находится в телеграм-сообществе. Там можно задать любой вопрос и повлиять на проект
Если вы зашли в тупик, то самое время поговорить с нашим асситентом Тота во вкладке "ИИ-помощник":
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Это нормально 🙆, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи. В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в обратной связи нашего сообщества
Ваше упражнение проверяется по этим тестам
package solution
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestGetWorkHours(t *testing.T) {
tests := []struct {
name string
input []int
expected []int
}{
{
name: "Full week",
input: []int{8, 8, 8, 8, 6, 0, 0},
expected: []int{8, 8, 8, 8, 6},
},
{
name: "Only five days",
input: []int{9, 9, 9, 9, 9},
expected: []int{9, 9, 9, 9, 9},
},
{
name: "Less than five days",
input: []int{8, 8, 8, 8},
expected: []int{},
},
{
name: "Empty schedule",
input: []int{},
expected: []int{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := GetWorkHours(tt.input)
assert.Equal(t, tt.expected, result)
})
}
}
Решение учителя откроется через:
20:00
