Нарезка — это очень часто используемый агрегатный тип в языке Go, он представляет собой последовательность переменной длины, а лежащий в основе объект ссылается на объект массива. Срез состоит из трех частей: указателя, длины и емкости. Указатель на адрес памяти базового элемента массива, соответствующего собственному первому элементу среза.
Объявление типа среза выглядит следующим образом:
type slice struct {
array unsafe.Pointer
len int
cap int
}
Данные базового массива могут совместно использоваться несколькими слайсами, а диапазоны массивов, на которые ссылаются, могут перекрываться. Используя эту функцию слайсов, мы можем выполнять такие операции, как инверсия, фильтрация и дедупликация слайсов в исходном пространстве памяти, так что нет необходимости объявлять слайс, указывающий на новую память, для сохранения результатов, тем самым экономя место в памяти и расширение потребления базового массива, что очень эффективно, когда длина среза достаточно велика.
В следующих примерах показаны все операции, выполняемые над пространством памяти нарезанного базового массива.Следует отметить, что эти операции генерируют новые срезы на базовом массиве, а также изменяют базовый массив.
удалить элемент в указанной позиции
Следующая функция удаляет позицию индекса из исходного среза.i
Элементы на
func remove(slice []int, i int) []int {
copy(slice[i:], slice[i+1:])
return slice[:len(slice)-1]
}
func main() {
s := []int{5, 6, 7, 8, 9}
fmt.Println(remove(s, 2)) // "[5 6 8 9]"
}
Встроенная функция копирования упрощает копирование слайса на другой слайс того же типа.
элемент фильтра
Следующая функция отфильтровывает элементы среза, удовлетворяющие условию, из среза входного источника и возвращает новый срез, состоящий из элементов, удовлетворяющих условию.
type funcType func(T) bool //代表筛选逻辑函数,可以按需实现
func filter(a []T, f funcType) []T {
b := a[:0]
for _, x := range a {
if f(x) {
b = append(b, x)
}
}
return b
}
Обратный срез
func reverse(a []T) []T {
for i := len(a)/2-1; i >= 0; i-- {
opp := len(a)-1-i
a[i], a[opp] = a[opp], a[i]
}
return a
}
сгруппированные фрагменты
Следующая функция получает[]int
тип исходного фрагментаactions
, возвращает вложенный слайс, сгруппированный по заданной длине (это сложно объяснить, студенты, которые использовали PHP, могут понять это как версию Goarray_chunk 函数
, см. пример ниже, если он не использовался). Предположим, что значение фасета равно:[]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
, задайте длину элементов в группеbatchSize
равно 3, сгруппированный срез, возвращаемый после вызова функции,[[0 1 2] [3 4 5] [6 7 8] [9]]
func chunk(actions []int, batchSize int) []int {
var batches [][]int
for batchSize < len(actions) {
actions, batches = actions[batchSize:], append(batches, actions[0:batchSize:batchSize])
}
batches = append(batches, actions)
return batches
}
func main() {
actions := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
batchSize := 3
chunks = chunk(actions, batchSize)
//chunks 为[[0 1 2] [3 4 5] [6 7 8] [9]]
}
Здесь, кстати, полное выражение среза имеет вид:
input[low:high:max]
Эффект последнего максимума заключается в том, что кепка (емкость) сгенерированного слайса равнаmax - low
.
Дедупликация на месте (только для сопоставимых типов слайсов)
import "sort"
func main() {
in := []int{3,2,1,4,3,2,1,4,1} // any item can be sorted
sort.Ints(in)
j := 0
for i := 1; i < len(in); i++ {
if in[j] == in[i] {
continue
}
j++
in[j] = in[i]
}
result := in[:j+1]
fmt.Println(result) // [1 2 3 4]
}
Некоторые примеры в статье взяты из официальной вики-страницы GitHub golang, которая знакомит с множеством навыков нарезки.GitHub.com/gowaves/go/me…