EMZETT.
Login

Kurz: final haeufigkeit = <String, int>{}; for (final w in woerter) { haeufigkeit.update(w, (n) => n + 1, ifAbsent: () => 1); } final top = haeufigkeit.entries.toList() ..sort((a, b) { final c = b.value.compareTo(a.value).

Teil des Kurses Dart

Kapitel 7 von 8 im Kurs Dart (Abschnitt „Projekte“). Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

Projekt 1: Wörter zählen

void main() {
  const text = '''
Dart ist schnell. Dart ist modern, und Dart macht Spaß!
Modern und schnell: das ist Dart.
''';
  final woerter = RegExp(r'[a-zäöüß]+')
      .allMatches(text.toLowerCase())
      .map((m) => m.group(0)!)
      .toList();
 
  final haeufigkeit = <String, int>{};
  for (final w in woerter) {
    haeufigkeit.update(w, (n) => n + 1, ifAbsent: () => 1);
  }
  final top = haeufigkeit.entries.toList()
    ..sort((a, b) {
      final c = b.value.compareTo(a.value);
      return c != 0 ? c : a.key.compareTo(b.key);
    });
 
  print('${woerter.length} Wörter, ${haeufigkeit.length} verschiedene');
  for (final e in top.take(4)) {
    print('${e.key.padRight(8)} ${'#' * e.value} ${e.value}');
  }
  print('Längstes Wort: ${woerter.reduce((a, b) => a.length >= b.length ? a : b)}');
}

Ausgabe:

16 Wörter, 8 verschiedene
dart     #### 4
ist      ### 3
modern   ## 2
schnell  ## 2
Längstes Wort: schnell

Projekt 2: Lagerverwaltung mit Klassen

class Artikel {
  final String name;
  final double preis;
  int menge;
  Artikel(this.name, this.preis, this.menge);
  double get wert => preis * menge;
  @override
  String toString() => '${name.padRight(10)} $menge x ${preis.toStringAsFixed(2)} = ${wert.toStringAsFixed(2)}';
}
 
class Lager {
  final Map<String, Artikel> _artikel = {};
 
  void aufnehmen(String name, double preis, int menge) {
    if (menge <= 0) throw ArgumentError('Menge muss positiv sein');
    _artikel.update(name, (a) { a.menge += menge; return a; }, ifAbsent: () => Artikel(name, preis, menge));
  }
 
  void entnehmen(String name, int menge) {
    final a = _artikel[name];
    if (a == null) throw StateError('Artikel $name unbekannt');
    if (a.menge < menge) throw StateError('Nur ${a.menge} von $name vorhanden');
    a.menge -= menge;
  }
 
  double get gesamtwert => _artikel.values.fold(0.0, (s, a) => s + a.wert);
  List<Artikel> get sortiert => _artikel.values.toList()..sort((a, b) => b.wert.compareTo(a.wert));
}
 
void main() {
  final lager = Lager();
  lager.aufnehmen('Schrauben', 0.12, 500);
  lager.aufnehmen('Bohrer', 14.9, 12);
  lager.aufnehmen('Schrauben', 0.12, 250);
  lager.aufnehmen('Muttern', 0.08, 300);
  for (final test in [() => lager.entnehmen('Bohrer', 5), () => lager.entnehmen('Bohrer', 50), () => lager.entnehmen('Nägel', 1), () => lager.aufnehmen('X', 1, 0)]) {
    try {
      test();
      print('ok');
    } catch (e) {
      print('Fehler: ${e is Error ? e.toString().replaceFirst(RegExp(r'^\w+: '), '') : e}');
    }
  }
  lager.sortiert.forEach(print);
  print('Gesamtwert: ${lager.gesamtwert.toStringAsFixed(2)}');
}

Ausgabe:

ok
Fehler: Bad state: Nur 7 von Bohrer vorhanden
Fehler: Bad state: Artikel Nägel unbekannt
Fehler: Invalid argument(s): Menge muss positiv sein
Bohrer     7 x 14.90 = 104.30
Schrauben  750 x 0.12 = 90.00
Muttern    300 x 0.08 = 24.00
Gesamtwert: 218.30

Projekt 3: Algorithmen

int fib(int n, [Map<int, int>? memo]) {
  memo ??= {};
  if (n < 2) return n;
  return memo[n] ??= fib(n - 1, memo) + fib(n - 2, memo);
}
 
List<int> primzahlen(int bis) {
  final sieb = List.filled(bis + 1, true);
  sieb[0] = sieb[1] = false;
  for (var i = 2; i * i <= bis; i++) {
    if (sieb[i]) { for (var j = i * i; j <= bis; j += i) { sieb[j] = false; } }
  }
  return [for (var i = 0; i <= bis; i++) if (sieb[i]) i];
}
 
int? binaereSuche(List<int> liste, int ziel) {
  var lo = 0, hi = liste.length - 1;
  while (lo <= hi) {
    final mitte = (lo + hi) ~/ 2;
    if (liste[mitte] == ziel) return mitte;
    if (liste[mitte] < ziel) { lo = mitte + 1; } else { hi = mitte - 1; }
  }
  return null;
}
 
bool istPalindrom(String s) {
  final sauber = s.toLowerCase().replaceAll(RegExp(r'[^a-zäöüß]'), '');
  return sauber == sauber.split('').reversed.join();
}
 
List<int> quicksort(List<int> l) {
  if (l.length < 2) return l;
  final pivot = l[l.length ~/ 2];
  return [
    ...quicksort(l.where((x) => x < pivot).toList()),
    ...l.where((x) => x == pivot),
    ...quicksort(l.where((x) => x > pivot).toList()),
  ];
}
 
void main() {
  print(fib(60));
  print(primzahlen(50));
  print('${binaereSuche([1, 3, 5, 7, 9, 11], 7)} ${binaereSuche([1, 3, 5], 4)}');
  print('${istPalindrom('A man, a plan, a canal: Panama')} ${istPalindrom('Dart')}');
  print(quicksort([5, 2, 9, 1, 5, 6, 3]));
  print([for (var i = 1; i <= 15; i++) i % 15 == 0 ? 'FizzBuzz' : i % 3 == 0 ? 'Fizz' : i % 5 == 0 ? 'Buzz' : '$i'].join(' '));
}

Ausgabe:

1548008755920
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
3 null
true false
[1, 2, 3, 5, 5, 6, 9]
1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz

Merke

  • Mit Map.update, Sortierung mit Vergleichsfunktion und RegExp entstehen Auswertungen in wenigen Zeilen
  • Klassen kapseln Zustand, Exceptions melden Fehler; ArgumentError und StateError sind Standardfehler
  • Memoization (??=), Sieb, binäre Suche und Quicksort sind Standardübungen
  • Collection for und if erzeugen Listen deklarativ

Übungsaufgabe

Erweitere das Lager um eine Methode bericht(), die Artikel unter einer Mindestmenge ausgibt.

Quiz zur Selbstkontrolle

??= …?

  • Berechnet und speichert den Wert nur, wenn er noch fehlt (richtig)
  • Löscht memo
  • Vergleicht memo
  • Wirft einen Fehler

Weiter im Kurs

Zurück: Flutter und das Dart-Ökosystem

Weiter: Referenz und Spickzettel

Alle Kapitel: Dart im Überblick