Sortieren von Go-Wörterbüchern

GolangGolangBeginner
Jetzt üben

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

Im Gegensatz zu anderen Sprachen sind in Go Wörterbücher (Maps) ungeordnete Sammlungen. In diesem Lab werden wir lernen, wie man Wörterbücher sortiert und wie man sie flexibler einsetzen kann.

Schlüsselkonzepte:

  • Sortieren von Wörterbüchern
  • Tauschen von Schlüsseln und Werten in einem Wörterbuch
  • Slices von Wörterbüchern
  • Wörterbücher mit Slices als Werte
  • Eigenschaften von Wörterbüchern als Referenztypen

Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL go(("Golang")) -.-> go/BasicsGroup(["Basics"]) go(("Golang")) -.-> go/DataTypesandStructuresGroup(["Data Types and Structures"]) go(("Golang")) -.-> go/FunctionsandControlFlowGroup(["Functions and Control Flow"]) go(("Golang")) -.-> go/AdvancedTopicsGroup(["Advanced Topics"]) go/BasicsGroup -.-> go/values("Values") go/DataTypesandStructuresGroup -.-> go/slices("Slices") go/DataTypesandStructuresGroup -.-> go/maps("Maps") go/DataTypesandStructuresGroup -.-> go/structs("Structs") go/FunctionsandControlFlowGroup -.-> go/for("For") go/FunctionsandControlFlowGroup -.-> go/functions("Functions") go/AdvancedTopicsGroup -.-> go/sorting("Sorting") subgraph Lab Skills go/values -.-> lab-149095{{"Sortieren von Go-Wörterbüchern"}} go/slices -.-> lab-149095{{"Sortieren von Go-Wörterbüchern"}} go/maps -.-> lab-149095{{"Sortieren von Go-Wörterbüchern"}} go/structs -.-> lab-149095{{"Sortieren von Go-Wörterbüchern"}} go/for -.-> lab-149095{{"Sortieren von Go-Wörterbüchern"}} go/functions -.-> lab-149095{{"Sortieren von Go-Wörterbüchern"}} go/sorting -.-> lab-149095{{"Sortieren von Go-Wörterbüchern"}} end

Sortieren von Wörterbüchern

Erstellen Sie eine Datei map.go im Verzeichnis ~/project:

touch ~/project/map.go

Schreiben Sie den folgenden Code in die Datei map.go:

package main

import (
	"fmt"
)

func main() {
	// Declare and initialize a map with string keys and integer values
	// The map stores student names and their scores
	m := map[string]int{
		"Alice":   99, // Each key-value pair represents a student and their score
		"Bob":     38,
		"Charlie": 84,
	}

	// Iterate through the map using a for-range loop
	// 'key' represents student names, 'value' represents scores
	for key, value := range m {
		fmt.Println(key, value)
	}

	fmt.Println("\nInsert Data")

	// Demonstrate how to add a new key-value pair to the map
	// The syntax is: map[key] = value
	m["David"] = 25

	// Iterate again to show the updated map contents
	// Note that the order may be different in each execution
	for key, value := range m {
		fmt.Println(key, value)
	}
}

Führen Sie das Programm aus:

go run ~/project/map.go

Die Ausgabe des Programms könnte wie folgt aussehen:

Charlie 84
Bob 38
Alice 99

Insert Data
David 25
Charlie 84
Bob 38
Alice 99

Die Ausgabe kann variieren, da die Reihenfolge der eingefügten Daten nicht festgelegt ist. Dies ist ein Kernmerkmal von Go-Wörterbüchern (Maps) - sie garantieren keine bestimmte Reihenfolge der Elemente, wenn Sie sie durchlaufen.

Sie können versuchen, das Programm mehrmals auszuführen und beobachten, dass die Reihenfolge der eingefügten Daten variieren kann. Dies zeigt, dass Sie sich nicht auf die Reihenfolge der Elemente in einem Wörterbuch verlassen können.

Manchmal müssen wir jedoch das Wörterbuch nach dem Einfügen von Daten sortieren. Wie können wir das erreichen?

Da ein Wörterbuch selbst nicht sortiert werden kann, können wir es in ein Slice umwandeln und dann das Slice sortieren.

Sortieren nach Schlüssel

Zunächst lernen wir, wie man das Wörterbuch (Map) nach Schlüssel sortiert.

Hier sind die Schritte:

  • Konvertieren Sie die Schlüssel des Wörterbuchs in ein Slice. Ein Slice ist ein geordnetes, dynamisches Array, das wir sortieren können.
  • Sortieren Sie das Slice mit Go's eingebautem sort-Paket.
  • Holen Sie die entsprechenden Werte mit der Suchmethode des Wörterbuchs ab. Da wir die Reihenfolge der Schlüssel in unserem Slice kennen, können wir die Werte in der Map suchen und sie werden in der sortierten Schlüsselreihenfolge angezeigt.

Schreiben Sie den folgenden Code in die Datei map.go:

package main

import (
	"fmt"
	"sort"
)

func main() {
	// Initialize the dictionary
	m1 := map[int]string{
		3: "Bob",
		1: "Alice",
		2: "Charlie",
	}
	keys := make([]int, 0, len(m1)) // Initialize the slice with capacity. This is a performance optimization -  the slice will allocate memory equal to the size of the map initially, avoiding re-allocations.
	for key := range m1 {
		// Convert the key to a slice
		keys = append(keys, key)
	}
	// Sort the key slice using the sort package. The `sort.Ints()` function specifically sorts a slice of integers.
	sort.Ints(keys)
	for _, key := range keys {
		// The output is in order now
		fmt.Println(key, m1[key])
	}
}

Führen Sie das Programm aus:

go run ~/project/map.go

Die Ausgabe des Programms ist wie folgt:

1 Alice
2 Charlie
3 Bob

Durch diesen Ansatz haben wir es geschafft, das Wörterbuch basierend auf dem Schlüssel zu sortieren. Die Schlüssel werden in ein Slice extrahiert, sortiert und dann verwendet, um die entsprechenden Werte aus der Map abzurufen und auszugeben.

Tauschen von Schlüsseln und Werten in einem Wörterbuch

Bevor wir erklären, wie man nach Wert sortiert, lernen wir zunächst, wie man die Schlüssel und Werte in einem Wörterbuch (Map) tauscht.

Das Tauschen von Schlüsseln und Werten bedeutet, die Positionen von Schlüsseln und Werten in einem Wörterbuch zu vertauschen, wie in der folgenden Abbildung gezeigt:

Dictionary key value swap

Der Implementierungscode ist einfach. Schreiben Sie den folgenden Code in die Datei map.go:

package main

import "fmt"

func main() {
	m := map[string]int{
		"Alice":   99,
		"Bob":     38,
		"Charlie": 84,
	}
	m2 := map[int]string{}
	for key, value := range m {
		m2[value] = key
	}
	fmt.Println(m2)
}

Führen Sie das Programm aus:

go run ~/project/map.go

Die Ausgabe des Programms ist wie folgt:

map[38:Bob 84:Charlie 99:Alice]

Die Essenz dieses Codes besteht darin, die Schlüssel und Werte aus dem ursprünglichen Wörterbuch zu extrahieren und sie dann mit vertauschten Rollen wieder in das Wörterbuch einzufügen. Es ist einfach und unkompliziert. Beachten Sie, dass die Ausgabeordnung des getauschten Wörterbuchs variieren kann, da das Wörterbuch ungeordnet ist.

Sortieren nach Wert

Indem wir die Logik des Sortierens eines Wörterbuchs (Map) nach Schlüssel und das Tauschen von Schlüsseln und Werten in einem Wörterbuch kombinieren, können wir das Wörterbuch nach Wert sortieren.

So funktioniert es: Wir tauschen die Schlüssel und Werte und behandeln dann die getauschten Schlüssel (die ursprünglichen Werte) als Grundlage für unsere Sortierung. Anschließend verwenden wir die sortierten "Schlüssel" (die ursprünglichen Werte), um die entsprechenden ursprünglichen Schlüssel in der getauschten Map abzurufen.

Schreiben Sie den folgenden Code in die Datei map.go:

package main

import (
	"fmt"
	"sort"
)

func main() {
	// Initialize the dictionary
	m1 := map[string]int{
		"Alice":   99,
		"Bob":     38,
		"Charlie": 84,
	}

	// Initialize the reversed dictionary
	m2 := map[int]string{}
	for key, value := range m1 {
		// Generate the reversed dictionary m2 by swapping the key-value pairs
		m2[value] = key
	}

	values := make([]int, 0) // Initialize the sorting slice
	for _, value := range m1 {
		// Convert the values of the original dictionary to a slice
		values = append(values, value)
	}
	// Sort the value slice using the sort package
	sort.Ints(values)

	for _, value := range values {
		// The output is in order now
		fmt.Println(m2[value], value)
	}
}

Führen Sie das Programm aus:

go run ~/project/map.go

Die Ausgabe des Programms ist wie folgt:

Bob 38
Charlie 84
Alice 99

Jetzt haben wir das Wörterbuch basierend auf seinen Werten sortiert. Wir haben die Werte in ein Slice umgewandelt, das Slice sortiert und dann die sortierten Werte verwendet, um die entsprechenden ursprünglichen Schlüssel aus der getauschten Map abzurufen und auszugeben.

Sortieren mit sort.Slice

Wenn die Go-Version neuer als 1.7 ist, können wir die Funktion sort.Slice verwenden, um eine Map schnell nach Schlüssel oder Wert zu sortieren. sort.Slice ermöglicht es Ihnen, eine benutzerdefinierte Vergleichsfunktion anzugeben.

Hier ist ein Beispiel:

package main

import (
	"fmt"
	"sort"
)

func main() {
	m1 := map[int]int{
		21: 99,
		12: 98,
		35: 17,
		24: 36,
	}

	type kv struct {
		Key   int
		Value int
	}

	var s1 []kv

	for k, v := range m1 {
		s1 = append(s1, kv{k, v})
	}

	sort.Slice(s1, func(i, j int) bool {
		return s1[i].Key < s1[j].Key
	})

	fmt.Println("Sorted in ascending order by key:")
	for _, pair := range s1 {
		fmt.Printf("%d, %d\n", pair.Key, pair.Value)
	}
}

Führen Sie das Programm aus:

go run ~/project/map.go

Die Ausgabe ist wie folgt:

Sorted in ascending order by key:
12, 98
21, 99
24, 36
35, 17

In diesem Programm haben wir eine Struktur kv verwendet, um die Schlüssel-Wert-Paare aus der Map zu speichern. Anschließend haben wir das Slice der Strukturen mit der Funktion sort.Slice() und einer anonymen Vergleichsfunktion sortiert. Diese Vergleichsfunktion (func(i, j int) bool) bestimmt die Sortierreihenfolge basierend auf dem Key-Feld unserer Struktur.

Wir können auch sort.Slice verwenden, um die Map in absteigender Reihenfolge nach Schlüssel oder in aufsteigender Reihenfolge nach Wert zu sortieren, indem wir diese Vergleichsfunktion ändern. Dies bietet eine große Flexibilität bei der Sortierung unserer Map-Daten.

Kleiner Test

Erstellen Sie eine Datei map2.go und ändern Sie den Code aus dem vorherigen Abschnitt, um die Map in absteigender Reihenfolge basierend auf dem Wert zu sortieren.

Erwartete Ausgabe:

Führen Sie das Programm aus:

go run ~/project/map2.go
Sorted in descending order by value:
21, 99
12, 98
24, 36
35, 17

Anforderungen:

  • Die Datei map2.go sollte im Verzeichnis ~/project platziert werden.
  • Sie müssen die Funktion sort.Slice verwenden. Sie müssen die Vergleichsfunktion, die in sort.Slice im vorherigen Beispiel verwendet wurde, ändern.
✨ Lösung prüfen und üben

Slices von Wörterbüchern

Genauso wie wir Arrays oder Slices verwenden können, um verwandte Daten zu speichern, können wir auch Slices verwenden, deren Elemente Wörterbücher (Maps) sind. Dies ermöglicht es uns, Sammlungen von Map-Daten zu halten, was für die Arbeit mit strukturierten Informationen nützlich sein kann.

Schreiben Sie den folgenden Code in die Datei map.go:

package main

import "fmt"

func main() {
	// Declare a slice of maps and initialize it using make
	var mapSlice = make([]map[string]string, 3) // Creates a slice with a capacity of 3, where each element can be a `map[string]string`.
	for index, value := range mapSlice {
		fmt.Printf("index:%d value:%v\n", index, value)
	}
	fmt.Println("Initialization")
	// Assign values to the first element of the slice
	mapSlice[0] = make(map[string]string, 10) // Creates a map at the first index.
	mapSlice[0]["name"] = "labex"
	mapSlice[0]["password"] = "123456"
	mapSlice[0]["address"] = "Paris"
	for index, value := range mapSlice {
		fmt.Printf("index:%d value:%v\n", index, value)
	}
}

Führen Sie das Programm aus:

go run ~/project/map.go

Die Ausgabe des Programms ist wie folgt:

index:0 value:map[]
index:1 value:map[]
index:2 value:map[]
Initialization
index:0 value:map[address:Paris name:labex password:123456]
index:1 value:map[]
index:2 value:map[]

Der Code zeigt die Initialisierung eines Slices von Maps. Anfangs ist jedes Element im Slice eine leere Map. Anschließend erstellen und weisen wir eine Map dem ersten Element zu und füllen sie mit Daten. Dies zeigt, wie man eine Liste von Maps verwalten kann.

Wörterbücher mit Slices als Werte

Wir können auch Wörterbücher (Maps) verwenden, bei denen die Werte Slices sind, um mehr Daten in einem Wörterbuch zu speichern. Dies ermöglicht es uns, mehreren Werten einen einzelnen Schlüssel in einer Map zuzuordnen und effektiv eine "Eins-zu-Viele"-Beziehung zu erstellen.

Schreiben Sie den folgenden Code in die Datei map.go:

package main

import "fmt"

func main() {
	var sliceMap = make(map[string][]string, 3) // Declares a map where keys are strings and values are slices of strings. The 3 is a capacity hint.
	key := "labex"
	value, ok := sliceMap[key]  // Checks if the key exists
	if!ok {
		value = make([]string, 0, 2) // If it doesn't exist, initialize a new slice with capacity.
	}
	value = append(value, "Paris", "Shanghai") // Appends values to the slice.
	sliceMap[key] = value // Sets the slice as the value for our key in the map.
	fmt.Println(sliceMap)
}

Führen Sie das Programm aus:

go run ~/project/map.go

Die Ausgabe des Programms ist wie folgt:

map[labex:[Paris Shanghai]]

Der Code deklariert zunächst einen Map-Typ, bei dem die Werte Slices sind. Bevor neue Elemente dem zugehörigen Slice hinzugefügt werden, wird überprüft, ob der Schlüssel existiert. Dies zeigt ein gängiges Muster für die Verwaltung von Maps mit Slices als Werten.

Referenztyp-Eigenschaften von Wörterbüchern

Arrays sind Werttypen (value types). Wenn Sie sie zuweisen oder an Funktionen übergeben, wird eine Kopie erstellt. Änderungen an der Kopie wirken sich nicht auf das ursprüngliche Array aus. Maps hingegen sind Referenztypen (reference types). Das bedeutet, dass das Zuweisen und Übergeben einer Map an eine Funktion keine vollständige Kopie erstellt. Stattdessen wird die Map per Referenz übergeben.

Dies ist wichtig, da Änderungen, die innerhalb der Funktion vorgenommen werden, tatsächlich die ursprünglichen Map-Daten beeinflussen.

Schreiben Sie den folgenden Code in die Datei map.go:

package main

import "fmt"

func modifyMap(x map[string]int) {
	x["Bob"] = 100 // Modifies the map that was passed as an argument.
}

func main() {
	a := map[string]int{
		"Alice":   99,
		"Bob":     38,
		"Charlie": 84,
	}
	// Because the map is passed by reference, the modification in modifyMap changes the original dictionary
	modifyMap(a)
	fmt.Println(a) // map[Alice:99 Bob:100 Charlie:84]
}

Führen Sie das Programm aus:

go run ~/project/map.go

Die Ausgabe des Programms ist wie folgt:

map[Alice:99 Bob:100 Charlie:84]

In diesem Beispiel haben wir die Referenzübergabe-Eigenschaft einer Map gezeigt. Die Funktion modifyMap ändert die ursprüngliche Map, da a eine Referenz auf dieselben zugrunde liegenden Map-Daten ist. Es ist wichtig, dieses Verhalten zu verstehen, wenn Sie Maps an Funktionen übergeben.

Zusammenfassung

In diesem Lab haben wir die fortgeschrittene Verwendung von Maps in Go kennengelernt, einschließlich:

  • Das Sortieren von Maps nach Schlüssel oder Wert, was das Konvertieren der Map in einen Slice und anschließendes Sortieren des Slices beinhaltet.
  • Das Vertauschen von Schlüsseln und Werten in einer Map, wodurch eine neue Map mit umgekehrten Rollen erstellt wird.
  • Die Verwendung von Slices von Maps, was die Erstellung von Sammlungen verwandter Map-Daten ermöglicht.
  • Die Verwendung von Maps mit Slices als Werten, was es ermöglicht, mehreren Werten einen einzelnen Schlüssel zuzuordnen.
  • Die Referenztyp-Eigenschaften von Maps, bei denen Änderungen an einer übergebenen Map sich auch auf die ursprüngliche Map auswirken.

Das Verständnis dieser Konzepte ermöglicht es Ihnen, Go-Maps in realen Anwendungen effektiver zu nutzen.