Как создать срез непоследовательных индексов массива - PullRequest
3 голосов
/ 19 марта 2020

Я пытаюсь лучше понять нарезку.

Например, в Фортране, если у меня есть двумерный массив, я могу создать срез, используя matrix(:, (/2, 5, 9/)). Этот срез содержит только строки 2, 5 и 9. Я пытаюсь найти способ создать похожий срез в Go.

Я знаю, что могу использовать команду append следующим образом:

var slice [][N]
slice = append(arr[1],arr[4],arr[8])

и срез имеет правильные значения, но append копирует значения, поэтому, если я обновлю массив, мой срез не обновится.

Есть ли правильный способ сделать это в Go

1 Ответ

2 голосов
/ 19 марта 2020

Цитирование из Spe c: Типы срезов:

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

Срез всегда обозначает непрерывный сегмент базового массива, элементы нельзя пропускать между индексами начала и конца.

Использование кусок указателей

Вы можете имитировать поведение указателей, но тогда они будут указателями со всеми своими плюсами и минусами. Например:

const N = 3

s := make([][N]int, 10)
s[2] = [3]int{20, 21, 22}
s[5] = [3]int{50, 51, 52}
s[9] = [3]int{90, 91, 92}

s2 := []*[N]int{&s[2], &s[5], &s[9]}
for _, p := range s2 {
    fmt.Print(*p, " ")
}

s[2][0] = 66
fmt.Println()
for _, p := range s2 {
    fmt.Print(*p, " ")
}

После создания и заполнения s2 (из элементов s), мы изменяем элементы s и печатаем s2 снова, и мы видим измененные, обновленные ценность. Вывод (попробуйте на Go Playground ):

[20 21 22] [50 51 52] [90 91 92] 
[66 21 22] [50 51 52] [90 91 92]

Использование фрагмента фрагментов

фрагменты (заголовки фрагментов) аналогичны указателям: они небольшие, структурированные структуры данных, которые содержат указатель на первый элемент слайса, указывающий на где-то в базовом массиве. Подробнее см. Передаются ли golang срезы по значению? и , почему значения срезов могут иногда go устаревать, но никогда не отображать значения?

Так что если вы использовать ломтик слайса вместо слайса массивов, он будет работать без указателей (значения слайса уже содержат указатели).

См. этот пример:

s := make([][]int, 10)
s[2] = []int{20, 21, 22}
s[5] = []int{50, 51, 52}
s[9] = []int{90, 91, 92}

s2 := [][]int{s[2], s[5], s[9]}
fmt.Println(s2)

s[2][0] = 66
fmt.Println(s2)

Это выдаст (попробуйте на игровой площадке Go ):

[[20 21 22] [50 51 52] [90 91 92]]
[[66 21 22] [50 51 52] [90 91 92]]

См. связанный вопрос: Как выглядит представление памяти двумерного массива

...