Collections
Lerne, wie du mit Listen, Maps und Sets in Velisch arbeitest – inklusive mächtiger funktionaler Methoden wie map, filter und reduce.
Was du lernen wirst
- Listen erstellen und manipulieren
- Maps für Schlüssel-Wert-Paare nutzen
- Funktionale Methoden (map, filter, reduce) anwenden
- Collections mit Datenbank-Operationen verbinden
Listen (Arrays)
Listen sind geordnete Sammlungen von Elementen desselben Typs. Sie wachsen dynamisch und bieten schnellen Index-Zugriff.
Listen erstellen
// Direkte Initialisierung
let fruits = ["Apfel", "Banane", "Kirsche"];
// Mit explizitem Typ
let numbers: List<number> = [1, 2, 3, 4, 5];
// Leere Liste
let empty: List<string> = [];
// Liste mit einem Element
let single = ["Einziges Element"];Grundlegende Operationen
let fruits = ["Apfel", "Banane"];
// Elemente hinzufügen
fruits.push("Kirsche"); // Am Ende: ["Apfel", "Banane", "Kirsche"]
fruits.insert(0, "Ananas"); // An Position 0: ["Ananas", "Apfel", ...]
// Elemente abrufen
let first = fruits[0]; // → "Ananas"
let last = fruits.last(); // → "Kirsche"
let length = fruits.length(); // → 4
// Elemente entfernen
let removed = fruits.pop(); // Entfernt letztes Element
fruits.remove(1); // Entfernt an Index 1
// Prüfungen
let hasApple = fruits.contains("Apfel"); // → true
let isEmpty = fruits.isEmpty(); // → falseÜber Listen iterieren
let users = ["Anna", "Max", "Lisa"];
// Einfache Iteration
for (user in users) {
print("Hallo, {user}!");
}
// Mit Index
for (index, user in users) {
print("{index + 1}. {user}");
}
// Ausgabe:
// 1. Anna
// 2. Max
// 3. Lisa
// Rückwärts iterieren
for (user in users.reversed()) {
print(user);
}Set oder Map statt Listen.contains() auf einer Liste ist O(n), bei einem Set ist es O(1).Maps (Dictionaries)
Maps speichern Schlüssel-Wert-Paare und ermöglichen blitzschnellen Zugriff über den Schlüssel. Perfekt für Caches, Konfigurationen und gruppierte Daten.
Maps erstellen und verwenden
// Map erstellen
let scores = Map<string, number>.new();
// Werte setzen
scores.set("Anna", 95);
scores.set("Max", 88);
scores.set("Lisa", 92);
// Werte abrufen
let annaScore = scores.get("Anna"); // → 95
// Sicherer Zugriff mit getOrDefault
let unknownScore = scores.getOrDefault("Bob", 0); // → 0
// Prüfungen
if (scores.has("Anna")) {
print("Anna hat {scores.get("Anna")} Punkte");
}
// Entfernen
scores.remove("Max");
// Größe
let count = scores.size(); // → 2Über Maps iterieren
let config = Map<string, string>.new();
config.set("host", "localhost");
config.set("port", "8080");
config.set("env", "development");
// Über Schlüssel-Wert-Paare iterieren
for (key, value in config) {
print("{key} = {value}");
}
// Nur Schlüssel
for (key in config.keys()) {
print(key);
}
// Nur Werte
for (value in config.values()) {
print(value);
}📦 Praxisbeispiel: User-Cache
let userCache = Map<string, User>.new();
fn getUser(id: string): User {
// Erst im Cache suchen
if (userCache.has(id)) {
return userCache.get(id);
}
// Aus Datenbank laden
let user = db.find(User, id);
// Im Cache speichern
userCache.set(id, user);
return user;
}Funktionale Methoden
Velisch bietet mächtige funktionale Methoden, um Collections elegant zu transformieren. Diese Methoden können verkettet werden für ausdrucksstarken, lesbaren Code.
map – Elemente transformieren
Wendet eine Funktion auf jedes Element an und gibt eine neue Liste zurück:
let numbers = [1, 2, 3, 4, 5];
// Verdoppeln
let doubled = numbers.map(n => n * 2);
// → [2, 4, 6, 8, 10]
// In Strings umwandeln
let strings = numbers.map(n => "Nummer: {n}");
// → ["Nummer: 1", "Nummer: 2", ...]
// Komplexere Transformation
struct User { id: string, name: string, email: string }
let users = db.findAll(User);
let names = users.map(user => user.name);
// → ["Anna", "Max", "Lisa"]filter – Elemente filtern
Behält nur Elemente, die eine Bedingung erfüllen:
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// Gerade Zahlen
let evens = numbers.filter(n => n % 2 == 0);
// → [2, 4, 6, 8, 10]
// Größer als 5
let big = numbers.filter(n => n > 5);
// → [6, 7, 8, 9, 10]
// Aktive Benutzer
let activeUsers = users.filter(user => user.isActive);
// Mit komplexer Bedingung
let admins = users.filter(user => {
return user.role == "admin" && user.isActive;
});reduce – Zu einem Wert aggregieren
Reduziert eine Liste auf einen einzelnen Wert:
let numbers = [1, 2, 3, 4, 5];
// Summe berechnen
let sum = numbers.reduce((acc, n) => acc + n, 0);
// → 15
// Maximum finden
let max = numbers.reduce((acc, n) => if (n > acc) n else acc, numbers[0]);
// → 5
// Objekt zusammenbauen
struct CartItem { name: string, price: number }
let cart = [
CartItem { name: "Buch", price: 19.99 },
CartItem { name: "Kaffee", price: 4.50 },
];
let total = cart.reduce((sum, item) => sum + item.price, 0.0);
// → 24.49Methoden verketten
Die wahre Macht zeigt sich beim Verketten mehrerer Operationen:
struct Order {
id: string,
userId: string,
total: number,
status: string,
}
let orders = db.findAll(Order);
// Komplexe Pipeline: Abgeschlossene Bestellungen eines Users summieren
let userTotal = orders
.filter(o => o.userId == "user_123") // Nur User's Bestellungen
.filter(o => o.status == "completed") // Nur abgeschlossene
.map(o => o.total) // Nur Beträge extrahieren
.reduce((sum, t) => sum + t, 0.0); // Summieren
// Top 3 Namen alphabetisch sortiert
let topNames = users
.filter(u => u.score > 90)
.map(u => u.name)
.sorted()
.take(3);find()Erstes passendes Element
users.find(u => u.id == "1")any()Mindestens einer erfüllt
users.any(u => u.isAdmin)all()Alle erfüllen Bedingung
users.all(u => u.verified)Collections & Datenbank
In der Praxis arbeiten Collections oft mit Datenbank-Ergebnissen zusammen. Velisch integriert SeaORM nahtlos für typsichere Queries.
struct User {
id: string,
name: string,
email: string,
role: string,
createdAt: string,
}
// CRUD mit Collections
// Alle User abrufen
@GET("/api/users")
fn getUsers(): List<User> {
return db.findAll(User);
}
// User mit Filter
@GET("/api/users/admins")
fn getAdmins(): List<User> {
return db.query(User)
.where("role", "=", "admin")
.findAll();
}
// User erstellen
@POST("/api/users")
fn createUser(name: string, email: string): User {
let user = User {
id: generateId(),
name: name,
email: email,
role: "user",
createdAt: now(),
};
return db.save(user);
}
// Mehrere User auf einmal erstellen (Batch)
@POST("/api/users/batch")
fn createUsers(users: List<CreateUserInput>): List<User> {
let created = users.map(input => {
return User {
id: generateId(),
name: input.name,
email: input.email,
role: "user",
createdAt: now(),
};
});
return db.saveAll(created);
}db.query().where().where() baut nur die Query auf –.findAll() führt sie aus.Zusammenfassung
Was du gelernt hast:
- Listen erstellen, manipulieren und iterieren
- Maps für schnellen Key-Value-Zugriff
- map(), filter(), reduce() verketten
- Collections mit SeaORM DB-Queries
Nächste Schritte:
- Closures für komplexere Transformationen
- Pattern Matching für elegante Datenverarbeitung