Skip to content

Instantly share code, notes, and snippets.

@proudlygeek
Created February 3, 2015 00:59
Show Gist options
  • Save proudlygeek/31dc8425ccb356824717 to your computer and use it in GitHub Desktop.
Save proudlygeek/31dc8425ccb356824717 to your computer and use it in GitHub Desktop.
LRU Cache Implementation
/**
* LRU Cache
*
* http://www.codewars.com/kata/53b406e67040e51e17000c0a
*
*/
function LRUCache(capacity, init) {
var data = init || {};
var timestamps = {};
var capacity = capacity;
var getTimestamp = function() {
var time = Date.now();
while(time === Date.now());
return Date.now();
};
var findLRU = function() {
var keys = Object.keys(timestamps);
return keys
.reduce(function(acc, x) {
if (timestamps[x] < acc.time) {
return {key: x, time: timestamps[x]} ;
} else { return acc;}
}, {key: keys[0], time: timestamps[keys[0]] });
};
var cache = function(key, val) {
if (!key) return data;
if (key && val) {
setCache(key, val);
}
if (this.size > this.capacity) {
var lruItem = findLRU();
deleteCache(lruItem.key);
}
return this;
}.bind(this);
var setCache = function(key, value) {
if (!this[key]) {
Object.defineProperty(this, key, {
get: function() { return data[key]; },
set: function(value) { data[key] = value; timestamps[key] = getTimestamp(); },
enumerable: true,
configurable: true
});
}
this[key] = value;
}.bind(this);
var deleteCache = function(key) {
if (typeof this[key] === 'function' || key === 'capacity' || key === 'size') {
return false;
}
if (typeof data[key] !== 'undefined' && data[key]) {
delete data[key];
delete this[key];
}
if (typeof timestamps[key] !== 'undefined') {
delete timestamps[key];
}
return true;
}.bind(this);
Object.defineProperty(this, 'size', {
get: function() {
return Object.keys(data).length;
}
});
Object.defineProperty(this, 'cache', {
value: cache,
enumerable: false,
writable: false,
configurable: false
});
Object.defineProperty(this, 'delete', {
value: function(key) { return deleteCache(key); },
enumerable: false,
writable: false,
configurable: false
});
Object.defineProperty(this, 'capacity', {
get: function() { return capacity; },
set: function(value) {
for (var i = 0; i < (this.size - value); i++) {
var lruItem = findLRU();
deleteCache(lruItem.key);
}
}
});
for (key in init) {
setCache(key, init[key]);
}
}
var store = new LRUCache(3, {a: 1});
Test.assertEquals(store.size, 1, 'store.size');
Test.assertEquals(store.capacity, 3, 'store.capacity');
Test.assertEquals(store.a, 1, 'store.a');
Test.assertEquals(store.cache('b', 2)['b'], 2, 'store.b');
store.a = 5;
Test.assertEquals(store.a, 5, 'store.a');
store.cache('c', 3).cache('d', 4);
Test.assertEquals(store.b, undefined, 'store.b');
Test.assertEquals(store.c, 3, 'store.c');
Test.assertEquals(store.d, 4, 'store.d');
Test.assertEquals(store.a, 5, 'store.a');
Test.assertEquals(store.size, 3, 'store.size');
Test.assertEquals(store.delete('delete'), false, "store.delete('delete')");
Test.assertEquals(store.delete('d'), true, "store.delete('d')");
Test.assertEquals(store.d, undefined, 'store.d');
Test.assertEquals(store.delete('e'), true, "store.delete('e')");
Test.assertEquals(store.size, 2, 'store.size');
store.cache('c', 4);
Test.assertEquals(store.c, 4, 'store.c');
store.capacity = 1;
Test.assertEquals(Object.keys(store).length, 1, "Object.keys(store).length");
Test.assertEquals(Object.keys(store)[0], 'c', "Object.keys(store).length");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment