Skip to content

Instantly share code, notes, and snippets.

@anushshukla
Last active March 1, 2023 19:56
Show Gist options
  • Select an option

  • Save anushshukla/6199ba4358a53e1be3763b393560d40d to your computer and use it in GitHub Desktop.

Select an option

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
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