Zum Hauptinhalt springen

BiDirectionalMap

Eine bidirektionale Map (BiMap) hält eine Eins-zu-Eins-Zuordnung zwischen Schlüsseln und Werten aufrecht und ermöglicht effiziente O(1) Lookups in beide Richtungen.

Installation

npm install @msnkr/data-structures

Verwendung

import { BiDirectionalMap } from '@msnkr/data-structures';

const biMap = new BiDirectionalMap<string, number>();

API-Referenz

Eigenschaften

  • size: number - Anzahl der Schlüssel-Wert-Paare in der Map

Methoden

Setzen und Abrufen von Elementen

// Schlüssel-Wert-Paar setzen - O(1)
biMap.set('one', 1);

// Wert nach Schlüssel abrufen - O(1)
const value = biMap.get('one');

// Schlüssel nach Wert abrufen - O(1)
const key = biMap.getKey(1);
Bidirektionale Lookups

Anders als bei normalen Maps ermöglicht BiMap effiziente Lookups nach Werten in O(1) Zeit, um Schlüssel zu finden.

Existenz prüfen

// Schlüssel prüfen - O(1)
const hasKey = biMap.hasKey('one');

// Wert prüfen - O(1)
const hasValue = biMap.hasValue(1);

Elemente löschen

// Nach Schlüssel löschen - O(1)
const removedByKey = biMap.deleteKey('one');

// Nach Wert löschen - O(1)
const removedByValue = biMap.deleteValue(1);

// Alle Zuordnungen löschen - O(1)
biMap.clear();

Iteration

// Über alle Schlüssel iterieren
for (const key of biMap.keys()) {
console.log(key);
}

// Über alle Werte iterieren
for (const value of biMap.values()) {
console.log(value);
}

// Über alle Einträge iterieren
for (const [key, value] of biMap.entries()) {
console.log(`${key} => ${value}`);
}

// forEach verwenden
biMap.forEach((value, key, map) => {
console.log(`${key} bildet ab auf ${value}`);
});

Hilfsmethoden

// Aus Einträgen erstellen - O(n)
const entries: [string, number][] = [
['one', 1],
['two', 2],
];
const biMap = BiDirectionalMap.fromEntries(entries);

// In Objekt konvertieren - O(n)
const obj = biMap.toObject();

Beispiele

Grundlegende Verwendung

const biMap = new BiDirectionalMap<string, number>();

// Zuordnungen setzen (unterstützt Verkettung)
biMap.set('one', 1).set('two', 2).set('three', 3);

// Bidirektionale Lookups
console.log(biMap.get('one')); // 1
console.log(biMap.getKey(2)); // "two"

console.log(biMap.hasKey('three')); // true
console.log(biMap.hasValue(1)); // true

HTTP-Statuscode-Zuordnung

const statusCodes = new BiDirectionalMap<number, string>();

statusCodes.set(200, 'OK');
statusCodes.set(404, 'Not Found');
statusCodes.set(500, 'Internal Server Error');

// Nach Code suchen
console.log(statusCodes.get(404)); // "Not Found"

// Nach Nachricht suchen
console.log(statusCodes.getKey('OK')); // 200

Ländercode-Verzeichnis

const countryCodes = new BiDirectionalMap<string, string>();

countryCodes.set('US', 'United States');
countryCodes.set('GB', 'United Kingdom');
countryCodes.set('FR', 'France');

// Name nach Code abrufen
console.log(countryCodes.get('US')); // "United States"

// Code nach Name abrufen
console.log(countryCodes.getKey('France')); // "FR"

Umgang mit doppelten Werten (Eins-zu-Eins-Beschränkung)

const biMap = new BiDirectionalMap<string, number>();

biMap.set('one', 1);
biMap.set('another', 1); // Überschreibt vorherige Zuordnung

console.log(biMap.get('one')); // undefined (Zuordnung entfernt)
console.log(biMap.get('another')); // 1
console.log(biMap.getKey(1)); // "another"

console.log(biMap.size); // 1 (nur eine Zuordnung existiert)
Eins-zu-Eins-Beschränkung

BiMap erzwingt Eins-zu-Eins-Zuordnungen. Das Setzen eines Schlüssels mit einem bereits existierenden Wert entfernt das vorherige Schlüssel-Wert-Paar.

Benutzer-ID zu Benutzername-Zuordnung

const userRegistry = new BiDirectionalMap<number, string>();

// Benutzer registrieren
userRegistry.set(1, 'alice');
userRegistry.set(2, 'bob');
userRegistry.set(3, 'charlie');

// Benutzername nach ID suchen
const username = userRegistry.get(2); // "bob"

// ID nach Benutzername suchen
const userId = userRegistry.getKey('alice'); // 1

// Prüfen ob Benutzername vergeben ist
if (userRegistry.hasValue('newuser')) {
console.log('Benutzername bereits vergeben!');
}

Sprachübersetzung

const translations = new BiDirectionalMap<string, string>();

translations.set('hello', 'hallo');
translations.set('goodbye', 'auf wiedersehen');
translations.set('thank you', 'danke');

// Englisch zu Deutsch
console.log(translations.get('hello')); // "hallo"

// Deutsch zu Englisch
console.log(translations.getKey('auf wiedersehen')); // "goodbye"

Zeitkomplexität

OperationDurchschnittSchlimmstenfalls
setO(1)O(1)
getO(1)O(1)
getKeyO(1)O(1)
hasKeyO(1)O(1)
hasValueO(1)O(1)
deleteKeyO(1)O(1)
deleteValueO(1)O(1)
clearO(1)O(1)

Best Practices

Wann BiMap verwenden

  • ✅ Bidirektionale Lookups erforderlich (Schlüssel zu Wert und Wert zu Schlüssel)
  • ✅ Eins-zu-Eins-Beziehung zwischen Schlüsseln und Werten
  • ✅ Häufige Reverse-Lookup-Operationen
  • ✅ Pflege eindeutiger Identifier-Zuordnungen

Wann BiMap nicht verwenden

  • ❌ Ein Schlüssel kann mehrere Werte haben
  • ❌ Nur Einweg-Lookups erforderlich
  • ❌ Werte müssen nicht eindeutig sein

Verwandte Datenstrukturen

  • Map - Einweg-Schlüssel-Wert-Zuordnung, erlaubt doppelte Werte
  • Set - Sammlung eindeutiger Werte ohne Schlüssel-Wert-Paare
  • SortedMap - Nach Schlüsseln sortierte Map

TypeScript-Tipps

// Generics für Typsicherheit verwenden
const stringToNumber = new BiDirectionalMap<string, number>();
stringToNumber.set('one', 1);

// Typprüfung
const value: number | undefined = stringToNumber.get('one');
const key: string | undefined = stringToNumber.getKey(1);

// Interface-Unterstützung
interface User {
id: number;
username: string;
}

const userMap = new BiDirectionalMap<number, User>();
userMap.set(1, { id: 1, username: 'alice' });