Ejercicio: Uso de matrices
Las matrices de Go son una estructura de datos de longitud fija de un tipo determinado. Pueden tener cero o más elementos, y es necesario definir su tamaño al declararlas o inicializarlas. Además, no es posible cambiar su tamaño una vez creadas. Por estos motivos, las matrices no se suelen usar en los programas de Go, aunque son la base de los segmentos y las asignaciones.
Declaración de matrices
Para declarar una matriz en Go, hay que definir el tipo de datos de sus elementos y el número de elementos que puede contener. Luego se puede acceder a cada elemento de la matriz con la notación de subíndice, donde cero es el primer elemento y el último es uno menos que la longitud de la matriz (length - 1).
Por ejemplo, vamos a usar el código siguiente:
package main
import "fmt"
func main() {
var a [3]int
a[1] = 10
fmt.Println(a[0])
fmt.Println(a[1])
fmt.Println(a[len(a)-1])
}
Al ejecutar el código anterior, se obtiene el siguiente resultado:
0
10
0
Aunque se ha declarado una matriz, no se obtiene un error al acceder a sus elementos. De manera predeterminada, Go inicializa cada elemento con el tipo de datos predeterminado. En este caso, el valor predeterminado de int
es cero, Sin embargo, puede asignar un valor a una posición determinada, como ya hicimos con a[1] = 10
. También se puede acceder a ese elemento mediante la misma notación. Además, observe que se ha usado a[0]
para referenciar el primer elemento. Para referenciar el último elemento, usamos a[len(a)-1]
. La función len
es una función integrada de Go para obtener el número de elementos de una matriz, segmento o asignación.
Inicialización de matrices
También puede inicializar una matriz con valores distintos a los predeterminados al declararla. Por ejemplo, puede usar el código siguiente para ver y probar la sintaxis:
package main
import "fmt"
func main() {
cities := [5]string{"New York", "Paris", "Berlin", "Madrid"}
fmt.Println("Cities:", cities)
}
Ejecute el código anterior; debería ver este resultado:
Cities: [New York Paris Berlin Madrid ]
Aunque la matriz debería tener cinco elementos, no es necesario asignar un valor a todos. Como se ha visto antes, la última posición presenta una cadena vacía porque es el valor predeterminado de un tipo de datos de cadena.
Puntos suspensivos en matrices
Otra forma de declarar e inicializar una matriz cuando no se sabe cuántas posiciones se van a necesitar, pero sí cuál es el conjunto de elementos de datos, es usar puntos suspensivos (...
), como en este ejemplo:
q := [...]int{1, 2, 3}
Vamos a modificar el programa empleado en la sección anterior para usar puntos suspensivos. El código debería tener un aspecto como el de este ejemplo:
package main
import "fmt"
func main() {
cities := [...]string{"New York", "Paris", "Berlin", "Madrid"}
fmt.Println("Cities:", cities)
}
Ejecute el código anterior; debería ver un resultado similar, como en este ejemplo:
Cities: [New York Paris Berlin Madrid]
¿Puede ver la diferencia? No hay ninguna cadena vacía al final. La longitud de la matriz viene determinada por las cadenas colocadas al inicializarla. No se reserva memoria que no se sabe si se va a necesitar.
Otra manera interesante de inicializar una matriz es usar puntos suspensivos y especificar únicamente un valor en la última posición. Por ejemplo, use el código siguiente:
package main
import "fmt"
func main() {
numbers := [...]int{99: -1}
fmt.Println("First Position:", numbers[0])
fmt.Println("Last Position:", numbers[99])
fmt.Println("Length:", len(numbers))
}
Ejecute este código y obtendrá este resultado:
First Position: 0
Last Position: -1
Length: 100
Observe cómo la longitud de la matriz es 100 porque ha especificado un valor en la posición 99ª. La primera posición imprime el valor predeterminado (cero).
Matrices multidimensionales
Go admite las matrices multidimensionales cuando se necesita trabajar con estructuras de datos complejas. Vamos a crear un programa en el que se declare e inicialice una matriz bidimensional. Use el código siguiente:
package main
import "fmt"
func main() {
var twoD [3][5]int
for i := 0; i < 3; i++ {
for j := 0; j < 5; j++ {
twoD[i][j] = (i + 1) * (j + 1)
}
fmt.Println("Row", i, twoD[i])
}
fmt.Println("\nAll at once:", twoD)
}
Ejecute el programa anterior; debería ver un resultado como el de este ejemplo:
Row 0 [1 2 3 4 5]
Row 1 [2 4 6 8 10]
Row 2 [3 6 9 12 15]
All at once: [[1 2 3 4 5] [2 4 6 8 10] [3 6 9 12 15]]
Ha declarado una matriz bidimensional que especifica cuántas posiciones tendría la matriz en la segunda dimensión, como esta var twoD [3][5]int
. Podría imaginarse esta matriz como una estructura de datos con columnas y filas, como una hoja de cálculo o una matriz. En este punto, todas las posiciones tienen un valor predeterminado de cero. En el bucle for
vamos a inicializar cada posición con un patrón de valor diferente en cada fila. Por último, imprima todos sus valores en el terminal.
¿Qué ocurriría si quisiera declarar una matriz tridimensional? Puede adivinar cuál sería la sintaxis, ¿no? Puede hacerlo como en este ejemplo:
package main
import "fmt"
func main() {
var threeD [3][5][2]int
for i := 0; i < 3; i++ {
for j := 0; j < 5; j++ {
for k := 0; k < 2; k++ {
threeD[i][j][k] = (i + 1) * (j + 1) * (k + 1)
}
}
}
fmt.Println("\nAll at once:", threeD)
}
Ejecute el código anterior; debería ver un resultado como el de este ejemplo:
All at once: [[[1 2] [2 4] [3 6] [4 8] [5 10]] [[2 4] [4 8] [6 12] [8 16] [10 20]] [[3 6] [6 12] [9 18] [12 24] [15 30]]]
Si se aplica un formato más legible al resultado, se podría obtener algo parecido a este ejemplo:
All at once:
[
[
[1 2] [2 4] [3 6] [4 8] [5 10]
]
[
[2 4] [4 8] [6 12] [8 16] [10 20]
]
[
[3 6] [6 12] [9 18] [12 24] [15 30]
]
]
Observe cómo cambia la estructura con respecto a una matriz bidimensional. Se pueden seguir agregando más dimensiones según sea necesario, pero por ahora lo vamos a dejar aquí porque hay otros tipos de datos que explorar.