A TypeScript library providing two-way mapping functionality with order preservation. It is ideal for scenarios requiring bidirectional lookups while maintaining the insertion order of elements. This class offers an intuitive API that aligns with common data structure operations, making it suitable for a variety of use cases.
- Two-way Mapping: Enables association of keys with values and vice versa, allowing for efficient bidirectional lookups.
- Order Preservation: Keeps track of the insertion order of elements, ensuring predictable iteration and retrieval.
- Extendable: Designed to be easily extendable for various data types, catering to diverse application needs.
- TypeScript Support: Full TypeScript support ensures type safety and provides IntelliSense for an enhanced development experience in IDEs.
Two-Way Map
is versatile and can be utilized in various real-world scenarios, both in frontend and backend development.
-
UI Component State and Data Mapping: Manage state and data of interactive components like graphs or tables efficiently by mapping component IDs to their states or data objects, facilitating quick state lookups and rendering logic.
-
Caching User Inputs: In complex forms or multi-step inputs, use
Two-Way Map
to cache user inputs, aiding in validation, auto-fill features, and quick access to input values. -
Routing and Navigation: In Single Page Applications (SPAs), map route paths to corresponding view components or page titles for efficient routing and dynamic updates of browser titles or breadcrumbs.
-
Internationalization and Localization: Simplify the process of handling multiple languages by mapping translation keys to actual text, making it easier to update text or locate the key associated with specific translated content.
-
Database ID and Object Mapping: Efficiently map database IDs to their corresponding record objects and vice versa, enabling quick retrieval and management of database records.
-
Session and User Management: Utilize
Two-Way Map
for mapping session IDs to user objects or user-specific data, streamlining session management and user data retrieval. -
Reverse Lookup in APIs: Optimize the lookup and validation process in APIs that support querying by different fields, such as username, email, or user ID, by using
Two-Way Map
for quick field-value mapping. -
Data Synchronization: In microservices architecture or distributed systems, keep track of data entities and their corresponding states across different services, aiding in data synchronization and consistency.
These use cases demonstrate the Two-Way Map
's ability to enhance efficiency and simplify complex data handling tasks in both frontend and backend environments.
To install two-way-map
, use the following command:
npm install @solancer/two-way-map
import { TwoWayMap } from "@solancer/two-way-map";
const map = new TwoWayMap<string, number>();
// Adding key-value pairs
map.set("apple", 1);
map.set("banana", 2);
map.set("cherry", 3);
// Retrieving values
console.log(map.get("banana")); // Outputs: 2
console.log(map.getByValue(3)); // Outputs: 'cherry'
// Deleting an element
map.delete("banana");
// Trying to get deleted element
console.log(map.get("banana")); // Outputs: undefined
// Iterating over keys
for (const key of map.keys()) {
console.log(key);
}
// Iterating over values
for (const value of map.values()) {
console.log(value);
}
// Popping a value by key
console.log(map.pop("apple")); // Outputs: 1
// Popping the last item
console.log(map.popitem()); // Outputs: ['cherry', 3]
// Creating a copy of the map
const copyMap = map.copy();
// Clearing all items from the map
map.clear();
console.log(map.keys()); // Outputs: []
Let's combine several operations to demonstrate a more complex scenario:
const fruitMap = new TwoWayMap<string, number>();
// Adding fruits
fruitMap.set("apple", 1);
fruitMap.set("banana", 2);
fruitMap.set("cherry", 3);
// Displaying all fruits
console.log("Fruits in the map:", fruitMap.keys()); // Outputs: ['apple', 'banana', 'cherry']
// Checking a specific fruit
console.log("Banana's number:", fruitMap.get("banana")); // Outputs: 2
// Removing a fruit
fruitMap.delete("apple");
console.log("Fruits after deleting apple:", fruitMap.keys()); // Outputs: ['banana', 'cherry']
// Popping the last item
const lastFruit = fruitMap.popitem();
console.log("Popped the last fruit:", lastFruit); // Outputs: ['cherry', 3]
// Remaining fruits
console.log("Remaining fruits:", fruitMap.entries()); // Outputs: [['banana', 2]]
// Copying and clearing
const fruitMapCopy = fruitMap.copy();
fruitMap.clear();
console.log("Original map after clearing:", fruitMap.keys()); // Outputs: []
console.log("Copied map:", fruitMapCopy.entries()); // Outputs: [['banana', 2]]
A two-way map that allows for key-to-value and value-to-key mappings, preserving the order in which items are added.
constructor()
: Initializes a new instance of theTwoWayMap
class.
-
set(key: K, value: V): void
Adds or updates a key-value pair in the map.
Parameters:
key: K
- The key to set.value: V
- The value to be associated with the key.
-
get(key: K): V | undefined
Retrieves the value associated with a given key.
Parameters:
key: K
- The key whose value is to be retrieved.
Returns: The value associated with the key, or
undefined
if the key does not exist.
-
getByValue(value: V): K | undefined
Retrieves the key associated with a given value.
Parameters:
value: V
- The value whose key is to be retrieved.
Returns: The key associated with the value, or
undefined
if the value does not exist.
-
delete(key: K): boolean
Removes a key-value pair from the map.
Parameters:
key: K
- The key to remove.
Returns:
true
if the key was found and removed,false
otherwise.
-
keys(): K[]
Returns an array of keys in the map, in the order they were added.
Returns: An array of keys.
-
values(): V[]
Returns an array of values in the map, in the order their corresponding keys were added.
Returns: An array of values.
-
entries(): [K, V][]
Returns an array of [key, value] pairs in the map, in the order they were added.
Returns: An array of [key, value] pairs.
-
pop(key: K, defaultValue?: V): V | undefined
Removes the value for the given key and returns it, or returns the
defaultValue
if the key is not in the map.Parameters:
key: K
- The key to pop.defaultValue: V
(optional) - The value to return if the key is not found.
Returns: The value associated with the key, or
defaultValue
if provided, orundefined
.
-
popitem(last: boolean = true): [K, V] | undefined
Removes and returns the last (or first, if
last
isfalse
) key-value pair from the map.Parameters:
last: boolean
(optional) - Specifies whether to pop the last item (true
) or the first item (false
).
Returns: The last or first [key, value] pair if the map is not empty, or
undefined
if it is.
-
copy(): TwoWayMap<K, V>
Creates and returns a shallow copy of the map.
Returns: A new
TwoWayMap
instance that contains the same key-value pairs.
-
clear(): void
Removes all key-value pairs from the map.
The Two-Way Map
library is designed using a composite data structure that combines features of a Map and a LinkedList. This choice is driven by the specific requirements of bidirectional lookup and order preservation, ensuring both efficiency and functionality in scenarios where these features are crucial.
- The core of the
Two-Way Map
is built upon two Maps - one for the key-to-value mapping and another for the value-to-key mapping. This structure allows for constant-time (O(1)) lookup in both directions, which is a significant advantage over iterating through an array or a standard map where you would typically achieve O(n) lookup time.
- In addition to bidirectional lookup, preserving the insertion order is a key requirement for many use cases. To achieve this, the library utilizes a LinkedList. This allows us to maintain the order of elements as they are inserted, which is not possible with standard JavaScript objects or Maps.
- While this data structure provides significant benefits in terms of functionality, it does come with trade-offs, particularly in terms of memory usage. By maintaining two Maps and a LinkedList, the
Two-Way Map
can consume more memory than a simple Map or object. However, for many applications, this trade-off is justified by the benefits of quick bidirectional access and order preservation.
Two-Way Map
is ideal for applications where both the key and value are important for retrieval and where the order of elements matters - for instance, in UI state management, session handling, or complex data transformations.
- For applications that only require simple key-to-value mapping without the need for reverse lookup or order preservation, a standard Map or object would be more memory-efficient.
- If only order is important and not bidirectional mapping, an Array or a LinkedList might suffice.
The Two-Way Map
library is crafted to fill a specific niche where both bidirectional lookup and order preservation are required. It strikes a balance between performance and functionality, making it a suitable choice for a range of applications where these features provide a tangible benefit.
Contributions are always welcome! Feel free to open a pull request or an issue if you have suggestions or find a bug.
This project is licensed under the MIT License.