2016-10-01 2 views
15

Я учусь, пройдя через A Tour of Go. В одном из упражнений мне предлагается создать 2D-фрагмент из dy строк и dx столбцов, содержащих uint8. Мой текущий подход, который работает, заключается в следующем:Что представляет собой сжатый способ создания 2D-фрагмента в Go?

a:= make([][]uint8, dy)  // initialize a slice of dy slices 
for i:=0;i<dy;i++ { 
    a[i] = make([]uint8, dx) // initialize a slice of dx unit8 in each of dy slices 
} 

Я думаю, что перебор каждого ломтика, чтобы инициализировать его слишком многословный. И если бы срез имел больше размеров, код стал бы громоздким. Есть ли сжатый способ инициализации 2D (или n-мерных) срезов в Go?

ответ

25

Существует не более краткий путь, что вы сделали это «правильный» путь; потому что срезы всегда одномерные, но могут быть составлены для построения объектов с большими размерами. См. Этот вопрос для получения более подробной информации: Go: How is two dimensional array's memory representation.

Одна вещь, вы можете упростить на нем использовать for range конструкцию:

a := make([][]uint8, dy) 
for i := range a { 
    a[i] = make([]uint8, dx) 
} 

Также обратите внимание, что если вы инициализировать кусочек с composite literal, вы получите это за «бесплатно», например:

a := [][]uint8{ 
    {0, 1, 2, 3}, 
    {4, 5, 6, 7}, 
} 
fmt.Println(a) // Output is [[0 1 2 3] [4 5 6 7]] 

Да, у этого есть свои пределы, поскольку, похоже, вам нужно перечислить все элементы; но есть некоторые трюки, а именно, вам не нужно перечислять все значения, только те, которые не являются zero values типа элемента среза. Для получения дополнительной информации об этом см. Keyed items in golang array initialization.

Например, если вы хотите кусок, где первые 10 элементов являются нулями, а затем следует 1 и 2, он может быть создан так:

b := []uint{10: 1, 2} 
fmt.Println(b) // Prints [0 0 0 0 0 0 0 0 0 0 1 2] 

Также обратите внимание, что если вы будете использовать arrays вместо из slices, она может быть создана очень легко:

c := [5][5]uint8{} 
fmt.Println(c) 

Выход:

[[0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]] 

В случае массивов вам не нужно перебирать «внешний» массив и инициализировать «внутренние» массивы, поскольку массивы не являются дескрипторами, а значениями. Дополнительную информацию см. В блоге Arrays, slices (and strings): The mechanics of 'append'.

Попробуйте примеры на Go Playground.

0

Вы можете передать этот кусок кода -

package main 

import "fmt" 

func main() { 
    var row, col int 
    fmt.Print("enter rows cols: ") 
    fmt.Scan(&row, &col) 

    // allocate composed 2d array 
    a := make([][]int, row) 
    for i := range a { 
     a[i] = make([]int, col) 
    } 

    // array elements initialized to 0 
    fmt.Println("a[0][0] =", a[0][0]) 

    // assign 
    a[row-1][col-1] = 7 

    // retrieve 
    fmt.Printf("a[%d][%d] = %d\n", row-1, col-1, a[row-1][col-1]) 

    // remove only reference 
    a = nil 
    // memory allocated earlier with make can now be garbage collected. 
} 

Reference

+3

Кроме 'range', я не вижу разницы, что спросил OP и ваш пример кода. – eduncan911

-1

Я написал эту функцию для замены строк в 2D массива:

func lchange(l1 int, l2 int, a [][]float64) { 
    b := make([]float64, 1) 
    b = a[l1][:] 
    a[l1] = a[l2] 
    a[l2] = b 
} 
+0

Это не относится к вопросу. – hazrmard

Смежные вопросы