Go-Sprache: Mehrdimensionale Arrays

Go-Arrays

Ein mehrdimensionales Array ist ein Array von Arrays. Betrachten Sie es als eineDatentabelleoderMatrix, wobei auf jedes Element über mehrere Indizes zugegriffen werden kann.

Mehrdimensionale Arrays in Go können verwendet werden, um strukturierte Informationen wie tabellarische Daten, Matrixoperationen oder Spielbretter zu verarbeiten.

Grundlegende Konzepte

  • Eindimensionales Array: Wie Punkte auf einer Geraden, wird nur eine Koordinate (Index) benötigt, um ein bestimmtes Element zu finden.
  • Zweidimensionales Array: wie eine Tabelle, erfordert zwei Koordinaten: Zeile und Spalte
  • Dreidimensionales Array: wie ein Würfel, erfordert drei Koordinaten: Länge, Breite und Höhe
  • Höhere Dimensionen: theoretisch können Arrays viele Dimensionen haben, aber in der Praxis werden zwei- und dreidimensionale Arrays am häufigsten verwendet

Dies lässt sich mit unseren alltäglichen Parkplätzen vergleichen:

  • Eindimensionales Array= eine Reihe von Parkplätzen (man benötigt nur die Parkplatznummer)
  • Zweidimensionales Array= ein mehrstöckiges Parkhaus (man benötigt die Etage und die Parkplatznummer)
  • Dreidimensionales Array= mehrere mehrstöckige Parkhäuser (man benötigt die Parkhausnummer, die Etage und die Parkplatznummer)

Go unterstützt mehrdimensionale Arrays. Im Folgenden sind gängige Möglichkeiten zum Deklarieren mehrdimensionaler Arrays aufgeführt:

var variable_name [SIZE1][SIZE2]...[SIZEN] variable_type

Deklaration und Initialisierung:

// Deklariere ein zweidimensionales Array var arrayName [rows][cols]elementType // Deklarieren und initialisieren var arrayName [rows][cols]elementType = [rows][cols]elementType{initialValues}

Das folgende Beispiel deklariert ein dreidimensionales Integer-Array:

var threedim [5][10][4]int

Zweidimensionales Array

Ein zweidimensionales Array ist das einfachste mehrdimensionale Array. Ein zweidimensionales Array besteht im Wesentlichen aus eindimensionalen Arrays. Die Vorgehensweise zum Definieren eines zweidimensionalen Arrays ist wie folgt:

var arrayName [ x ][ y ] variable_type

variable_type ist der Datentyp in Go, arrayName ist der Array-Name. Ein zweidimensionales Array kann als Tabelle betrachtet werden, wobei x für die Zeilen und y für die Spalten steht. Das folgende Diagramm zeigt ein zweidimensionales Array a mit drei Zeilen und vier Spalten:

Auf Elemente in einem zweidimensionalen Array kann übera[ i ][ j ]zugegriffen werden.

Beispiel

package main

import "fmt"

func main() {
    // Schritt 1: Ein Array erstellen
    values := [][]int{}

    // Schritt 2: Verwende die Funktion append(), um einem leeren zweidimensionalen Array zwei Zeilen eindimensionaler Arrays hinzuzufügen
    row1 := []int{1, 2, 3}
    row2 := []int{4, 5, 6}
    values = append(values, row1)
    values = append(values, row2)

    // Schritt 3: Zwei Datenzeilen anzeigen
    fmt.Println("Zeile 1")
    fmt.Println(values[0])
    fmt.Println("Row 2")
    fmt.Println(values[1])

    // Schritt 4: Auf das erste Element zugreifen
    fmt.Println("First element:")
    fmt.Println(values[0][0])
}

Die Ausgabe des obigen Beispiels ist:

Row 1
[1 2 3]
Row 2
[4 5 6]
第一个元素为:
1

Initialisieren eines zweidimensionalen Arrays

Mehrdimensionale Arrays können mit geschweiften Klammern initialisiert werden. Das folgende Beispiel ist ein zweidimensionales Array mit 3 Zeilen und 4 Spalten:

a := [3][4]int{  
 {0, 1, 2, 3} ,   /*  第一行索引为 0 */
 {4, 5, 6, 7} ,   /*  第二行索引为 1 */
 {8, 9, 10, 11},   /* 第三行索引为 2 */
}
Hinweis:Im obigen Code muss die vorletzte Zeile}ein Komma haben, weil die letzte Zeile}Es muss nicht in einer einzigen Zeile stehen; es kann auch so geschrieben werden:
a := [3][4]int{  
 {0, 1, 2, 3} ,   /*  第一行索引为 0 */
 {4, 5, 6, 7} ,   /*  第二行索引为 1 */
 {8, 9, 10, 11}}   /* 第三行索引为 2 */

Das folgende Beispiel initialisiert ein zweidimensionales Array mit 2 Zeilen und 2 Spalten:

Beispiel

package main

import "fmt"

func main() {
    // Ein zweidimensionales Array erstellen
    sites := [2][2]string{}

    // Elemente zum zweidimensionalen Array hinzufügen
    sites[0][0] = "Google"
    sites[0][1] = "Example"
    sites[1][0] = "Taobao"
    sites[1][1] = "Weibo"

    // Ergebnis anzeigen
    fmt.Println(sites)
}

Die Ausgabe des obigen Beispiels ist:

[[Google Example] [Taobao Weibo]]

Zugriff auf ein zweidimensionales Array

Auf ein zweidimensionales Array wird zugegriffen, indem Koordinaten angegeben werden, wie z. B. der Zeilenindex und der Spaltenindex im Array. Zum Beispiel:

val := a[2][3]
oder 
var value int = a[2][3]

Im obigen Beispiel wurde auf das vierte Element in der dritten Zeile des zweidimensionalen Arrays val zugegriffen.

Ein zweidimensionales Array kann verschachtelte Schleifen verwenden, um Elemente auszugeben:

Beispiel

package main

import "fmt"

func main() {
   /* Array - 5 Zeilen 2 Spalten*/
   var a = [5][2]int{ {0,0}, {1,2}, {2,4}, {3,6},{4,8}}
   var i, j int

   /* Array-Elemente ausgeben */
   for  i = 0; i < 5; i++ {
      for j = 0; j < 2; j++ {
         fmt.Printf("a[%d][%d] = %d\n", i,j, a[i][j] )
      }
   }
}

Die Ausgabe des obigen Beispiels ist:

a[0][0] = 0
a[0][1] = 0
a[1][0] = 1
a[1][1] = 2
a[2][0] = 2
a[2][1] = 4
a[3][0] = 3
a[3][1] = 6
a[4][0] = 4
a[4][1] = 8

Das folgende Beispiel erstellt ein mehrdimensionales Array, bei dem die Anzahl der Elemente in jeder Dimension unterschiedlich ist:

Beispiel

package main

import "fmt"

func main() {
    // Ein leeres zweidimensionales Array erstellen
    animals := [][]string{}

    // Drei eindimensionale Arrays mit jeweils unterschiedlicher Länge erstellen
    row1 := []string{"Fisch", "Hai", "Aal"}
    row2 := []string{"Vogel"}
    row3 := []string{"Eidechse", "Salamander"}

    // Verwende die append()-Funktion, um ein eindimensionales Array zum zweidimensionalen Array hinzuzufügen
    animals = append(animals, row1)
    animals = append(animals, row2)
    animals = append(animals, row3)

    // Schleife zur Ausgabe
    for i := range animals {
        fmt.Printf("Zeile: %v\n", i)
        fmt.Println(animals[i])
    }
}

Die Ausgabe des obigen Beispiels ist:

Row: 0
[fish shark eel]
Row: 1
[bird]
Row: 2
[lizard salamander]

Zugriff auf Array-Elemente und deren Änderung

Zugriff auf Elemente

Beispiel

package main

import "fmt"

func main() {
    // Erstelle eine 3x3-Matrix
    matrix := [3][3]int{
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9},
    }
   
    // Zugriff auf ein einzelnes Element
    fmt.Println("Zeile 1, Spalte 2:", matrix[0][1])  // Ausgabe: 2
    fmt.Println("Zeile 3, Spalte 3:", matrix[2][2]) // Ausgabe: 9
   
    // Zugriff auf die gesamte Zeile
    fmt.Println("Zeile 2:", matrix[1])  // Ausgabe: [4 5 6]
   
    // Alle Elemente durchlaufen
    fmt.Println("\nAlle Elemente durchlaufen:")
    for i := 0; i < 3; i++ {
        for j := 0; j < 3; j++ {
            fmt.Printf("matrix[%d][%d] = %d\n", i, j, matrix[i][j])
        }
    }
}

Elemente ändern

Beispiel

package main

import "fmt"

func main() {
    // Eine 2x2-Nullmatrix erstellen
    var grid [2][2]int
   
    fmt.Println("Matrix vor der Änderung:", grid)
   
    // Das Element an einer bestimmten Position ändern
    grid[0][0] = 10
    grid[0][1] = 20
    grid[1][0] = 30
    grid[1][1] = 40
   
    fmt.Println("Matrix nach der Änderung:", grid)
   
    // Eine Zeile batchweise ändern
    grid[0] = [2]int{100, 200}
    fmt.Println("Nach Änderung der ersten Zeile:", grid)
}

Drei- und höherdimensionale Arrays

Beispiel für ein dreidimensionales Array

Beispiel

package main

import "fmt"

func main() {
    // Ein dreidimensionales 2x3x4-Array deklarieren
    // Kann verstanden werden als: 2 Ebenen, jede mit 3 Zeilen und 4 Spalten
    var cube [2][3][4]int
   
    // 3D-Array initialisieren
    cube = [2][3][4]int{
        { // Die erste Ebene
            {1, 2, 3, 4},
            {5, 6, 7, 8},
            {9, 10, 11, 12},
        },
        { // Die zweite Ebene
            {13, 14, 15, 16},
            {17, 18, 19, 20},
            {21, 22, 23, 24},
        },
    }
   
    // Zugriff auf 3D-Array-Elemente
    fmt.Println("cube[0][1][2] =", cube[0][1][2])  // Ausgabe: 7
    fmt.Println("cube[1][2][3] =", cube[1][2][3])  // Ausgabe: 24
   
    // Ein 3D-Array durchlaufen
    fmt.Println("\nInhalt des dreidimensionalen Arrays:)
    for i := 0; i < 2; i++ {
        fmt.Printf("Ebene %d:\n", i)
        for j := 0; j < 3; j++ {
            for k := 0; k < 4; k++ {
                fmt.Printf("%3d ", cube[i][j][k])
            }
            fmt.Println()
        }
        fmt.Println()
    }
}

siehe Abbildung unten:


Häufige Operationen mit mehrdimensionalen Arrays

1. Iterieren mit range

Beispiel

package main

import "fmt"

func main() {
    // Ein 2D-Array erstellen
    scores := [3][4]int{
        {85, 90, 78, 92},
        {88, 76, 95, 89},
        {92, 85, 88, 90},
    }
   
    fmt.Println("Notentabelle der Studierenden:")
   
    // range verwenden, um über das 2D-Array zu iterieren
    for i, row := range scores {
        fmt.Printf("Noten von Student %d: ", i+1)
        for j, score := range row {
            fmt.Printf("%d ", score)
            // Falls sowohl Index als auch Wert benötigt werden
            _ = j // Warnung vor unbenutzter Variable vermeiden
        }
        fmt.Println()
    }
   
    // Nur den Wert berücksichtigen, nicht den Index
    total := 0
    count := 0
    for _, row := range scores {
        for _, score := range row {
            total += score
            count++
        }
    }
    fmt.Printf("\nDurchschnittliche Punktzahl: %.2f\n", float64(total)/float64(count))
}

2. Die Array-Länge ermitteln

Beispiel

package main

import "fmt"

func main() {
    // Ein unregelmäßiges mehrdimensionales Array erstellen
    jagged := [3][3]int{
        {1, 2, 3},
        {4, 5},
        {6, 7, 8, 9}, // Hinweis: Dies führt zu einem Kompilierungsfehler, da jede Zeile dieselbe Länge haben muss
    }
   
    // Korrektes Beispiel: Array-Dimensionen ermitteln
    matrix := [4][5]int{}
   
    // Anzahl der Zeilen ermitteln
    rows := len(matrix)
    fmt.Println("Zeilen:", rows)  // Ausgabe: 4
   
    // Anzahl der Spalten in der ersten Zeile abrufen (alle Zeilen haben die gleiche Länge)
    cols := len(matrix[0])
    fmt.Println("Spalten:", cols)  // Ausgabe: 5
   
    // Gesamtzahl der Elemente abrufen
    totalElements := rows * cols
    fmt.Println("Gesamtzahl der Elemente:", totalElements)  // Ausgabe: 20
}

3. Array-Vergleich

Beispiel

package main

import "fmt"

func main() {
    // Zwei identische 2D-Arrays erstellen
    a := [2][2]int{{1, 2}, {3, 4}}
    b := [2][2]int{{1, 2}, {3, 4}}
    c := [2][2]int{{1, 2}, {3, 5}}
   
    // Arrays können direkt verglichen werden (nur wenn die Dimensionen exakt gleich sind)
    fmt.Println("a == b:", a == b)  // Ausgabe: true
    fmt.Println("a == c:", a == c)  // Ausgabe: false
   
    // Hinweis: Arrays unterschiedlicher Dimensionen können nicht verglichen werden
    // d := [2][3]int{{1, 2, 3}, {4, 5, 6}}
    // fmt.Println(a == d) // Kompilierfehler: Typen stimmen nicht überein
}

Praktische Anwendungsszenarien

Szenario 1: Spielbrett (Tic-Tac-Toe)

Beispiel

package main

import "fmt"

func main() {
    // Ein 3x3-Tic-Tac-Toe-Brett initialisieren
    var board [3][3]string
   
    // Als leer initialisieren
    for i := 0; i < 3; i++ {
        for j := 0; j < 3; j++ {
            board[i][j] = " "
        }
    }
   
    // Züge simulieren
    board[0][0] = "X"
    board[1][1] = "O"
    board[2][2] = "X"
   
    // Das Spielbrett ausgeben
    fmt.Println("Tic-Tac-Toe-Brett:")
    for i := 0; i < 3; i++ {
        for j := 0; j < 3; j++ {
            fmt.Printf(" %s ", board[i][j])
            if j < 2 {
                fmt.Printf("|")
            }
        }
        fmt.Println()
        if i < 2 {
            fmt.Println("---+---+---")
        }
    }
}

Szenario 2: Notenverwaltungssystem für Studenten

Beispiel

package main

import "fmt"

func main() {
    // Definiere: 3 Studenten, jeder Student hat 4 Kurse
    var grades [3][4]float64
   
    // Eingabe der Punkte der Studenten
    grades = [3][4]float64{
        {85.5, 90.0, 78.5, 92.0},  // Punkte von Student 1
        {88.0, 76.5, 95.0, 89.5},  // Punkte von Student 2
        {92.5, 85.0, 88.5, 90.0},  // Punkte von Student 3
    }
   
    // Berechne die Durchschnittspunktzahl jedes Studenten
    fmt.Println("Statistik der Studentenpunkte:")
    for i, studentGrades := range grades {
        sum := 0.0
        for _, grade := range studentGrades {
            sum += grade
        }
        average := sum / float64(len(studentGrades))
        fmt.Printf("Student %d: Durchschnittsnote = %.2f\n", i+1, average)
    }
   
    // Berechne die Durchschnittsnote jedes Kurses
    fmt.Println("\nKursdurchschnitt:")
    for j := 0; j < 4; j++ {
        sum := 0.0
        for i := 0; i < 3; i++ {
            sum += grades[i][j]
        }
        average := sum / 3.0
        fmt.Printf("Kurs %d: Durchschnittsnote = %.2f\n", j+1, average)
    }
}

Szenario 3: Bildpixelverarbeitung

Beispiel

package main

import "fmt"

func main() {
    // Ein einfaches 3x3-Graustufenbild simulieren
    // Wertebereich jedes Pixels: 0(schwarz) ~ 255(weiß)
    var image [3][3]int
   
    // Das Bild initialisieren (ein einfacher Farbverlauf)
    for i := 0; i < 3; i++ {
        for j := 0; j < 3; j++ {
            image[i][j] = (i + j) * 50
        }
    }
   
    // Das Originalbild anzeigen
    fmt.Println("Originalbild:")
    displayImage(image)
   
    // Bildverarbeitung: Helligkeit erhöhen
    fmt.Println("\nBild nach Helligkeitserhöhung:")
    for i := 0; i < 3; i++ {
        for j := 0; j < 3; j++ {
            // Helligkeit erhöhen, aber 255 nicht überschreiten
            newValue := image[i][j] + 50
            if newValue > 255 {
                newValue = 255
            }
            image[i][j] = newValue
        }
    }
    displayImage(image)
}

func displayImage(img [3][3]int) {
    for i := 0; i < 3; i++ {
        for j := 0; j < 3; j++ {
            fmt.Printf("%3d ", img[i][j])
        }
        fmt.Println()
    }
}

Hinweise und bewährte Verfahren

1. Array-Länge ist Teil des Typs

Beispiel

package main

import "fmt"

func main() {
    // Diese beiden sind unterschiedliche Typen!
    var a [2][3]int
    var b [3][2]int
   
    // Der folgende Code verursacht einen Kompilierungsfehler
    // a = b // Fehler: Typenkonflikt
   
    fmt.Printf("Typ von a: %T\n", a)  // [2][3]int
    fmt.Printf("Typ von b: %T\n", b)  // [3][2]int
}

2. Werttyp vs. Referenztyp

Beispiel

package main

import "fmt"

func main() {
    // Arrays sind Werttypen
    original := [2][2]int{{1, 2}, {3, 4}}
   
    // Eine Zuweisung erstellt eine Kopie
    copy := original
   
    // Das Ändern der Kopie wirkt sich nicht auf das ursprüngliche Array aus
    copy[0][0] = 100
   
    fmt.Println("Ursprüngliches Array:", original)  // [[1 2] [3 4]]
    fmt.Println("Kopiertes Array:", copy)      // [[100 2] [3 4]]
   
    // Wenn Sie Referenzsemantik benötigen, können Sie Slices verwenden (in späteren Artikeln eingeführt)
}

3. Leistungsüberlegungen

  • Zusammenhängender Speicher: Mehrdimensionale Arrays werden zusammenhängend im Speicher abgelegt, was einen schnellen Zugriff ermöglicht
  • Feste Größe: Die Länge eines Arrays wird zur Kompilierzeit festgelegt und kann nicht dynamisch geändert werden
  • Geeignete Szenarien: Wenn die Datengröße bekannt und fest ist, sind Arrays die beste Wahl

Häufig gestellte Fragen

F1: Was ist der Unterschied zwischen einem mehrdimensionalen Array und einem verschachtelten Slice?

Funktionen Mehrdimensionale Arrays Verschachtelte Slices
Size Fest, zur Kompilierzeit festgelegt Dynamisch, zur Laufzeit variabel
Gedächtnis Zusammenhängende Allokation Möglicherweise nicht zusammenhängend
Leistung Schnelle Zugriffsgeschwindigkeit Etwas langsamer, hat zusätzlichen Overhead
Anwendungsfall Datengröße bekannt Datengröße variabel

F2: Wie erstellt man ein unregelmäßiges zweidimensionales Array?

Go-Arrays erfordern, dass jede Zeile die gleiche Länge hat. Wenn Sie eine unregelmäßige Struktur benötigen, sollten Sie Slices verwenden:

Beispiel

// Verwenden Sie Slices, um unregelmäßige Strukturen zu erstellen
irregular := [][]int{
    {1, 2, 3},
    {4, 5},          // Diese Zeile hat nur 2 Elemente
    {6, 7, 8, 9},    // Diese Zeile hat 4 Elemente
}

F3: Kann ein mehrdimensionales Array als Funktionsparameter verwendet werden?

Ja, aber beachten Sie, dass Arrays Werttypen sind und das Übergeben großer Arrays Leistungskosten verursacht:

Beispiel

func processMatrix(matrix [3][3]int) [3][3]int {
    // Die Matrix verarbeiten...
    matrix[0][0] = 100
    return matrix
}

// Ein besserer Weg ist die Verwendung von Pointern oder Slices
func processMatrixPtr(matrix *[3][3]int) {
    matrix[0][0] = 100
}

Go-Arrays

Weitere Erweiterungen