Last active
March 1, 2023 19:56
-
-
Save anushshukla/6199ba4358a53e1be3763b393560d40d to your computer and use it in GitHub Desktop.
LRU Cache with pre-defined size having O(1) complexity for all operations
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| interface HashItem { | |
| value: string | |
| next: null | string | |
| } | |
| interface Hash { | |
| [key: string]: HashItem | |
| } | |
| interface ListConfig { | |
| maxSize: number | |
| } | |
| interface CacheStats { | |
| hits: number | |
| miss: number | |
| } | |
| const DEFAULT_MAX_SIZE = 3 | |
| class LRU { | |
| private _maxSize: number; | |
| private _hash: Hash; | |
| private _firstItem: string; | |
| private _lastItem: string; | |
| private _length: number; | |
| private _stats: CacheStats | |
| constructor(maxSize: number = DEFAULT_MAX_SIZE) { | |
| this._maxSize = maxSize; | |
| this._firstItem = ''; | |
| this._lastItem = ''; | |
| this._hash = {} as Hash; | |
| this._length = 0; | |
| this._stats = { | |
| hits: 0, | |
| miss: 0, | |
| } | |
| } | |
| /** | |
| * @param string $key | |
| * @param string $value | |
| * @return bool $result | |
| * Stores value against the key in the cache | |
| */ | |
| add(index: string, value: string) { | |
| if (this._maxSize < 1) { | |
| throw new Error('LRU max size should be greater than 0!'); | |
| } | |
| if (this._hash[index] && this._lastItem === index) { | |
| return; | |
| } | |
| if (this._length === 0) { | |
| this._firstItem = index; | |
| } | |
| if (this._length === this._maxSize) { | |
| const lastFirstItem = this._hash[this._firstItem] as HashItem; | |
| this.remove(this._firstItem); | |
| this._firstItem = lastFirstItem.next as string; | |
| } | |
| this._hash[index] = { | |
| value, | |
| next: null | |
| }; | |
| if (this._hash[this._lastItem]) { | |
| this._hash[this._lastItem].next = index; | |
| } | |
| this._lastItem = index; | |
| this._length++; | |
| } | |
| remove(index: string) { | |
| delete this._hash[index]; | |
| this._length--; | |
| } | |
| /** | |
| * @param string index | |
| * @return string | null HashItem | |
| * Gets the value of a key from the cache | |
| */ | |
| getFromCache(index: string) { | |
| const cache = this._hash[index] as HashItem; | |
| if (cache) { | |
| this.add(index, cache.value) | |
| this._stats.hits++; | |
| return cache.value; | |
| } | |
| this._stats.miss++; | |
| return null; | |
| } | |
| get cache() { | |
| return this._hash; | |
| } | |
| get stats() { | |
| return this._stats; | |
| } | |
| /** | |
| * @return int $count | |
| * Gets the number of successful cache hits so far | |
| */ | |
| allCacheHits() { | |
| return this.stats.hits; | |
| }; | |
| /** | |
| * @return int $count | |
| * Gets the number of unsuccessful cache hits so far | |
| */ | |
| allCacheMissed() { | |
| return this.stats.miss; | |
| } | |
| } | |
| const lru = new LRU(); | |
| lru.add("key1", "value1"); | |
| lru.add("key2", "value2"); | |
| lru.add("key5", "value5"); | |
| console.log('cache', lru.cache); // key1, key2, key5 | |
| lru.add("key8", "value8"); | |
| console.log('cache', lru.cache); // key2, key5, key8 | |
| lru.add("key2", "value2"); | |
| console.log('cache', lru.cache); // key5, key8, key2 | |
| lru.add("key3", "value3"); | |
| console.log('cache', lru.cache); // key8, key2, key3 | |
| lru.add("key3", "value3"); | |
| console.log('cache', lru.cache); // key8, key2, key3 | |
| console.log(lru.getFromCache('key2')); // "value2" | |
| console.log(lru.getFromCache('key5')); // null | |
| console.log(lru.allCacheHits()); // 1 | |
| console.log(lru.allCacheMissed()); // 1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment