LoginSignup
1
0

More than 3 years have passed since last update.

2次元スライスの切り出し

Last updated at Posted at 2019-05-15

TL;DR

正解例

よくある間違い

例えば、

[][]int[
  []int[11 12 13 14 15]
  []int[21 22 23 24 25]
  []int[31 32 33 34 35]
  []int[41 42 43 44 45]
  []int[51 52 53 54 55]
]

から

[][]int{
  []int[23 24]
  []int[33 34]
  []int[43 44]
]

↑この参照がほしい

arr[1:4][2:4]ってやると、

var arr = [][]int{
    []int{11, 12, 13, 14, 15},
    []int{21, 22, 23, 24, 25},
    []int{31, 32, 33, 34, 35},
    []int{41, 42, 43, 44, 45},
    []int{51, 52, 53, 54, 55},
}
sliced := arr[1:4][2:4]
for _, row := range sliced {
    fmt.Println(row)
}

// 結果
// [41 42 43 44 45]
// [51 52 53 54 55]

となってしまう。これは(arr[1:4])[2:4]と同義

arr[1:4]

0:[21 22 23 24 25]
1:[31 32 33 34 35]
2:[41 42 43 44 45]

から[2:4を]スライス

[41 42 43 44 45]
[51 52 53 54 55] (参照元のメモリには残ってる)

正解例

内部の配列のみ通常のスライス。

var arr = [][]int{
    []int{11, 12, 13, 14, 15},
    []int{21, 22, 23, 24, 25},
    []int{31, 32, 33, 34, 35},
    []int{41, 42, 43, 44, 45},
    []int{51, 52, 53, 54, 55},
}
// slice範囲
rf, rt, cf, ct := 1, 4, 2, 4
// slicing
sliced := make([][]int, rt-rf)
copy(sliced, arr[rf:rt]) // arr[rf:rt]のスライスを書き換えちゃうと、元の配列で内部配列のlengthが変わっちゃう
for i := range sliced {
    sliced[i] = sliced[i][cf:ct]
}
// show
fmt.Println("Source array")
for _, row := range arr {
    fmt.Println(row)
}
fmt.Println("\nSliced array 1:4,2:4")
for _, row := range sliced {
    fmt.Println(row)
}

// [23 24]
// [33 34]
// [43 44]

当然要素のメモリ参照は元の配列と同じなので、slicedを書き換えるとarrも書き換わる。

Playground

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0