C_C
C_C

Reputation: 47

How to create slice of nonconsecutive array indices

I'm trying to understand slicing better.

In Fortran, for instance, if I have a 2d array, I can create a slice using matrix(:, (/2, 5, 9/)). This slice contains just the rows 2, 5, and 9. I'm trying to find a way to create a similar slice in Go.

I know that I can use append like this:

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

and the slice has the right values, but append copies the values, so if I update the array, my slice does not update.

Is there a proper way to do this in Go?

Upvotes: 3

Views: 599

Answers (1)

icza
icza

Reputation: 418087

Quoting from Spec: Slice types:

A slice is a descriptor for a contiguous segment of an underlying array and provides access to a numbered sequence of elements from that array.

A slice always denotes a contiguous segment of an underlying array, elements cannot be skipped between the start and end indices.

Using a slice of pointers

You could mimic the behavior with pointers, but then they will be pointers with all their pros and cons. For example:

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, " ")
}

After creating and populating s2 (from elements of s), we modify elements of s, and print s2 again, and we see the changed, updated value. Output (try it on the Go Playground):

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

Using a slice of slices

Slices (slice headers) are similar to pointers: they are small, struct like data structures which contain a pointer to the first element of the slice, pointing to somewhere in an underlying array. For details, see Are golang slices passed by value? and why slice values can sometimes go stale but never map values?

So if you would use a slice of slices instead of a slice of arrays, it would work without pointers (slice values already contain pointers).

See this example:

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)

This will output (try it on the Go Playground):

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

See related question: How is two dimensional array's memory representation

Upvotes: 2

Related Questions