Lernziel
Nach dieser Lektion kannst du Arrays anlegen, Elemente lesen, hinzufügen, ändern und entfernen, mit einer Schleife durchlaufen und die wichtigsten Array-Funktionen nutzen.
Das Problem: Viele Werte, viele Variablen
Du willst die Namen deiner Freunde speichern. Mit Variablen sähe das so aus:
let friend1 = "Anna"
let friend2 = "Ben"
let friend3 = "Clara"Was passiert, wenn ein vierter Freund dazukommt? Eine neue Variable. Und wenn du alle begrüßen willst? Drei einzelne print-Befehle. Wenn die Anzahl vorher nicht feststeht, etwa weil der Nutzer selbst Freunde hinzufügt, funktioniert dieser Ansatz überhaupt nicht mehr.
Du brauchst eine Schachtel, in die beliebig viele Werte passen, in einer festen Reihenfolge. Das ist ein Array.
Ein Array anlegen
Ein Array schreibst du mit eckigen Klammern, die Werte trennst du mit Kommas:
let friends = ["Anna", "Ben", "Clara"]
print(friends) // ["Anna", "Ben", "Clara"]Die eckigen Klammern [ und ] tippst du auf der deutschen Mac-Tastatur mit ⌥ 5 und ⌥ 6.
Die Motivations-App aus Lektion 0.4 hatte übrigens genau so ein Array: die Liste der Sprüche.
Der Typ eines Arrays
Alle Elemente eines Arrays haben denselben Typ. Swift leitet ihn wieder selbst ab:
let friends = ["Anna", "Ben", "Clara"] // [String]
let scores = [12, 7, 23] // [Int]
let prices = [1.99, 4.5, 0.99] // [Double][String] liest du als „Array von Strings“. Gemischte Arrays wie ["Anna", 34, true] lässt Swift nicht zu.
Ein leeres Array
Bei einem leeren Array kann Swift den Typ nicht erraten. Du musst ihn angeben:
var shoppingList: [String] = []Auf Elemente zugreifen
Jedes Element hat eine Position, den Index. Und hier kommt eine Besonderheit: Gezählt wird ab 0.
let friends = ["Anna", "Ben", "Clara"]
// 0 1 2
print(friends[0]) // Anna
print(friends[2]) // ClaraDas erste Element hat den Index 0, das letzte den Index Anzahl − 1. Am Anfang ist das ungewohnt, aber fast alle Programmiersprachen zählen so. Du gewöhnst dich schnell daran.
Für den Anfang und das Ende gibt es bequeme Abkürzungen:
print(friends.first) // Optional("Anna")
print(friends.last) // Optional("Clara")Was das Optional(...) bedeutet, lernst du in Lektion 1.8. Kurz gesagt: Bei einem leeren Array gäbe es kein erstes Element, und Swift macht dich darauf aufmerksam.
Wie viele Elemente?
print(friends.count) // 3
print(friends.isEmpty) // falseEin Array verändern
Ein Array mit let ist unveränderlich. Willst du Elemente hinzufügen oder entfernen, brauchst du var:
var friends = ["Anna", "Ben"]
// Hinzufügen
friends.append("Clara") // ["Anna", "Ben", "Clara"]
friends.insert("Zoe", at: 0) // ["Zoe", "Anna", "Ben", "Clara"]
friends += ["David", "Eva"] // hängt mehrere an
// Ändern
friends[1] = "Annika" // ersetzt "Anna"
// Entfernen
friends.remove(at: 0) // entfernt "Zoe"
friends.removeLast() // entfernt "Eva"
friends.removeAll() // leert das ArrayTipp
append heißt „anhängen“, insert „einfügen“, remove „entfernen“. Die englischen Namen sind fast immer sprechend. Wenn du etwas suchst, tipp nach dem Punkt einfach das englische Wort, und Xcode schlägt dir die passende Funktion vor.
Arrays durchlaufen
Jetzt kommen die Schleifen aus Lektion 1.5 ins Spiel:
let friends = ["Anna", "Ben", "Clara"]
for friend in friends {
print("Hallo, \(friend)!")
}
// Hallo, Anna!
// Hallo, Ben!
// Hallo, Clara!Ein vierter Freund? Einfach ins Array, die Schleife bleibt gleich. Genau das ist die Stärke von Arrays.
Mit Index durchlaufen
Brauchst du zusätzlich die Position, hilft enumerated():
for (index, friend) in friends.enumerated() {
print("\(index + 1). \(friend)")
}
// 1. Anna
// 2. Ben
// 3. Clara(index, friend) holt zwei Werte gleichzeitig aus jedem Durchlauf. So ein Paar von Werten heißt Tupel. Mehr brauchst du darüber im Moment nicht zu wissen.
Nützliche Fähigkeiten
Arrays bringen eine Menge fertiger Funktionen mit:
let scores = [12, 7, 23, 7, 15]
scores.contains(23) // true
scores.firstIndex(of: 7) // Optional(1)
scores.min() // Optional(7)
scores.max() // Optional(23)
scores.sorted() // [7, 7, 12, 15, 23]
scores.reversed() // in umgekehrter Reihenfolge
scores.shuffled() // zufällig gemischt
scores.randomElement() // zufälliges ElementrandomElement() kennst du aus der Motivations-App. Und die Summe aller Elemente kannst du mit einer Schleife berechnen:
var total = 0
for score in scores {
total += score
}
print(total) // 64sort() oder sorted()?
Achte auf den kleinen Unterschied:
var names = ["Clara", "Anna", "Ben"]
let sortedNames = names.sorted() // gibt ein NEUES sortiertes Array zurück
print(names) // ["Clara", "Anna", "Ben"], unverändert
names.sort() // sortiert das Array SELBST
print(names) // ["Anna", "Ben", "Clara"]Diese Namensregel gilt in Swift überall: Endet der Name auf -ed oder -ing (sorted, reversed, shuffled), bekommst du ein neues Ergebnis zurück, und das Original bleibt gleich. Ohne Endung (sort, reverse, shuffle) wird das Original verändert, und dafür braucht es var.
Typische Fehler
Index außerhalb des Arrays
let friends = ["Anna", "Ben", "Clara"]
print(friends[3])Fehlermeldung
Laufzeitfehler: Index out of range
Der höchste Index ist 2, nicht 3. Das ist der häufigste Absturzgrund bei Arrays. Prüf vorher mit friends.count, oder nutze first, last und Schleifen, die nie über das Ende hinauslaufen.
Array mit let verändern
Fehlermeldung
Cannot use mutating member on immutable value: 'friends' is a 'let' constant
Mach aus let ein var.
Falscher Typ
var scores = [12, 7, 23]
scores.append("zehn")Fehlermeldung
Cannot convert value of type 'String' to expected argument type 'Int'
In ein [Int] passen nur ganze Zahlen.
Leeres Array ohne Typ
var items = []Fehlermeldung
Empty collection literal requires an explicit type
Lösung: var items: [String] = [].
FAQ
Anfänger
Was bedeutet das überhaupt?Warum fängt das Zählen bei 0 an?
Historisch kommt das daher, wie Computer Daten im Speicher ablegen: Der Index ist der Abstand vom Anfang. Das erste Element ist 0 Schritte vom Anfang entfernt. Die gute Nachricht: Mit for friend in friends musst du dich darum meist gar nicht kümmern.
Kann ein Array dasselbe Element mehrfach enthalten?
Ja. [7, 7, 7] ist ein gültiges Array. Wenn jedes Element nur einmal vorkommen darf, ist ein Set besser. Das lernst du in der nächsten Lektion.
Gibt es eine Obergrenze für die Größe? Praktisch nur den Speicher des Geräts. Arrays mit Tausenden Elementen sind völlig normal.
Fortgeschritten
Warum verhält es sich so?Wie greife ich auf einen Teil eines Arrays zu?
Mit einem Bereich: friends[0...1] liefert die ersten beiden Elemente. Etwas lesbarer sind oft friends.prefix(2) (die ersten zwei) und friends.suffix(2) (die letzten zwei).
Kann ich Arrays von Arrays bauen?
Ja, zum Beispiel für ein Spielfeld: let board = [[1, 2, 3], [4, 5, 6]]. Mit board[1][2] greifst du auf die 6 zu. Der Typ ist [[Int]].
Warum liefert min() ein Optional?
Weil ein leeres Array kein kleinstes Element hat. Swift zwingt dich, diesen Fall zu bedenken. Wie das geht, zeigen die Lektionen 1.8 und 1.9.
Profi
Was passiert unter der Haube?Wird ein Array beim Weitergeben kopiert? Logisch ja: Arrays sind Werttypen (Lektion 1.13). Gibst du ein Array an eine andere Variable, kann eine Änderung dort das Original nicht beeinflussen. Technisch kopiert Swift aber erst, wenn tatsächlich etwas verändert wird (Copy-on-Write). Das Weitergeben selbst ist deshalb sehr günstig.
Wie schnell sind die Operationen?
Zugriff per Index und append sind praktisch sofort erledigt, egal wie groß das Array ist. insert(at: 0) und remove(at: 0) müssen dagegen alle folgenden Elemente verschieben, und contains muss im schlimmsten Fall alle Elemente anschauen. Bei sehr großen Datenmengen lohnt sich deshalb manchmal ein Set oder Dictionary.
Übungen
Übung 1: Lieblingsfilme
Leg ein Array mit drei Lieblingsfilmen an. Füg einen vierten hinzu, ersetze den zweiten durch einen anderen Film und gib dann alle Filme nummeriert aus.
Lösung Übung 1Erst selbst probieren!
var movies = ["Inception", "Up", "Amélie"]
movies.append("Interstellar")
movies[1] = "Coco"
for (index, movie) in movies.enumerated() {
print("\(index + 1). \(movie)")
}Übung 2: Durchschnittstemperatur
Gegeben sind die Temperaturen einer Woche: [12.5, 14.0, 9.5, 11.0, 15.5, 17.0, 13.5]. Berechne den Durchschnitt und zähle, an wie vielen Tagen es wärmer als 13 Grad war.
Lösung Übung 2Erst selbst probieren!
let temperatures = [12.5, 14.0, 9.5, 11.0, 15.5, 17.0, 13.5]
var sum = 0.0
var warmDays = 0
for temperature in temperatures {
sum += temperature
if temperature > 13 {
warmDays += 1
}
}
let average = sum / Double(temperatures.count)
print("Durchschnitt: \(average) Grad") // 13.285…
print("Warme Tage: \(warmDays)") // 4Übung 3: Duplikate entfernen
Schreib eine Schleife, die aus [3, 1, 3, 2, 1, 4] ein neues Array ohne Duplikate erzeugt. Die ursprüngliche Reihenfolge soll erhalten bleiben: Erwartet ist [3, 1, 2, 4].
Lösung Übung 3Erst selbst probieren!
let numbers = [3, 1, 3, 2, 1, 4]
var unique: [Int] = []
for number in numbers {
if !unique.contains(number) {
unique.append(number)
}
}
print(unique) // [3, 1, 2, 4]Für kleine Arrays ist das völlig in Ordnung. Bei sehr großen wird contains langsam, weil es jedes Mal das ganze Array durchsucht. Wie es mit einem Set schneller geht, siehst du in der nächsten Lektion.
Zusammenfassung
- Ein Array speichert viele Werte desselben Typs in einer festen Reihenfolge.
- Der Index beginnt bei 0. Ein Zugriff außerhalb führt zum Absturz.
append,insert,removeverändern das Array, dafür braucht esvar.for item in arraydurchläuft alle Elemente,enumerated()liefert zusätzlich den Index.- -ed-Funktionen (
sorted) liefern ein neues Array, die anderen (sort) ändern das Original.
Spickzettel
var list = ["A", "B"] // [String]
var empty: [Int] = [] // leeres Array
list[0] // "A"
list.count list.isEmpty
list.append("C")
list.insert("Z", at: 0)
list.remove(at: 0)
list.contains("B")
for item in list { ... }
for (i, item) in list.enumerated() { ... }