forked from TheAlgorithms/JavaScript
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
merge: Improved
LRUCache
(TheAlgorithms#953)
* feat: added new validation test casses & methods * style: formated with standard * feat: added parse method & test cases * docs: added js docs * chore: added default import export
- Loading branch information
1 parent
55da7a1
commit 81c771b
Showing
2 changed files
with
164 additions
and
21 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,40 +1,146 @@ | ||
class LRUCache { | ||
// LRU Cache to store a given capacity of data | ||
#capacity | ||
|
||
/** | ||
* @param {number} capacity - the capacity of LRUCache | ||
* @returns {LRUCache} - sealed | ||
*/ | ||
constructor (capacity) { | ||
this.cache = new Map() | ||
this.capacity = capacity | ||
if (!Number.isInteger(capacity) || capacity < 0) { | ||
throw new TypeError('Invalid capacity') | ||
} | ||
|
||
this.#capacity = ~~capacity | ||
this.misses = 0 | ||
this.hits = 0 | ||
this.miss = 0 | ||
this.cache = new Map() | ||
|
||
return Object.seal(this) | ||
} | ||
|
||
get info () { | ||
return Object.freeze({ | ||
misses: this.misses, | ||
hits: this.hits, | ||
capacity: this.capacity, | ||
size: this.size | ||
}) | ||
} | ||
|
||
get size () { | ||
return this.cache.size | ||
} | ||
|
||
cacheInfo () { | ||
// Return the details for the cache instance [hits, misses, capacity, current_size] | ||
return `CacheInfo(hits=${this.hits}, misses=${this.miss}, capacity=${this.capacity}, current size=${this.cache.size})` | ||
get capacity () { | ||
return this.#capacity | ||
} | ||
|
||
set capacity (newCapacity) { | ||
if (newCapacity < 0) { | ||
throw new RangeError('Capacity should be greater than 0') | ||
} | ||
|
||
if (newCapacity < this.capacity) { | ||
let diff = this.capacity - newCapacity | ||
|
||
while (diff--) { | ||
this.#removeLeastRecentlyUsed() | ||
} | ||
} | ||
|
||
this.#capacity = newCapacity | ||
} | ||
|
||
/** | ||
* delete oldest key existing in map by the help of iterator | ||
*/ | ||
#removeLeastRecentlyUsed () { | ||
this.cache.delete(this.cache.keys().next().value) | ||
} | ||
|
||
/** | ||
* @param {string} key | ||
* @returns {*} | ||
*/ | ||
has (key) { | ||
key = String(key) | ||
|
||
return this.cache.has(key) | ||
} | ||
|
||
/** | ||
* @param {string} key | ||
* @param {*} value | ||
*/ | ||
set (key, value) { | ||
key = String(key) | ||
// Sets the value for the input key and if the key exists it updates the existing key | ||
if (this.cache.size === this.capacity) { | ||
// delete oldest key existing in map | ||
this.cache.delete(this.cache.keys().next().value) | ||
if (this.size === this.capacity) { | ||
this.#removeLeastRecentlyUsed() | ||
} | ||
|
||
this.cache.set(key, value) | ||
} | ||
|
||
/** | ||
* @param {string} key | ||
* @returns {*} | ||
*/ | ||
get (key) { | ||
key = String(key) | ||
// Returns the value for the input key. Returns null if key is not present in cache | ||
if (this.cache.has(key)) { | ||
const value = this.cache.get(key) | ||
|
||
// refresh the cache to update the order of key | ||
this.cache.delete(key) | ||
this.cache.set(key, value) | ||
this.hits += 1 | ||
|
||
this.hits++ | ||
return value | ||
} else { | ||
this.miss += 1 | ||
return null | ||
} | ||
|
||
this.misses++ | ||
return null | ||
} | ||
|
||
/** | ||
* @param {JSON} json | ||
* @returns {LRUCache} | ||
*/ | ||
parse (json) { | ||
const { misses, hits, cache } = JSON.parse(json) | ||
|
||
this.misses += misses ?? 0 | ||
this.hits += hits ?? 0 | ||
|
||
for (const key in cache) { | ||
this.set(key, cache[key]) | ||
} | ||
|
||
return this | ||
} | ||
|
||
/** | ||
* @param {number} indent | ||
* @returns {JSON} - string | ||
*/ | ||
toString (indent) { | ||
const replacer = (_, value) => { | ||
if (value instanceof Set) { | ||
return [...value] | ||
} | ||
|
||
if (value instanceof Map) { | ||
return Object.fromEntries(value) | ||
} | ||
|
||
return value | ||
} | ||
|
||
return JSON.stringify(this, replacer, indent) | ||
} | ||
} | ||
|
||
export { LRUCache } | ||
export default LRUCache |
This file contains 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