You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					107 lines
				
				2.3 KiB
			
		
		
			
		
	
	
					107 lines
				
				2.3 KiB
			| 
											3 years ago
										 | // https://medium.com/dsinjs/implementing-lru-cache-in-javascript-94ba6755cda9
 | ||
|  | 
 | ||
|  | class Node { | ||
|  |   constructor(key, value, next = null, prev = null) { | ||
|  |     this.key = key; | ||
|  |     this.value = value; | ||
|  |     this.next = next; | ||
|  |     this.prev = prev; | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | export default class LRUCache { | ||
|  |   //set default limit of 10 if limit is not passed.
 | ||
|  |   constructor(limit = 10) { | ||
|  |     this.size = 0; | ||
|  |     this.limit = limit; | ||
|  |     this.head = null; | ||
|  |     this.tail = null; | ||
|  |     this.cache = {}; | ||
|  |   } | ||
|  | 
 | ||
|  |   // Write Node to head of LinkedList
 | ||
|  |   // update cache with Node key and Node reference
 | ||
|  |   put(key, value){ | ||
|  |     this.ensureLimit(); | ||
|  | 
 | ||
|  |     if(!this.head){ | ||
|  |       this.head = this.tail = new Node(key, value); | ||
|  |     }else{ | ||
|  |       const node = new Node(key, value, this.head); | ||
|  |       this.head.prev = node; | ||
|  |       this.head = node; | ||
|  |     } | ||
|  | 
 | ||
|  |     //Update the cache map
 | ||
|  |     this.cache[key] = this.head; | ||
|  |     this.size++; | ||
|  |   } | ||
|  | 
 | ||
|  |   // Read from cache map and make that node as new Head of LinkedList
 | ||
|  |   get(key){ | ||
|  |     if(this.cache[key]){ | ||
|  |       const value = this.cache[key].value; | ||
|  | 
 | ||
|  |       // node removed from it's position and cache
 | ||
|  |       this.remove(key) | ||
|  |       // write node again to the head of LinkedList to make it most recently used
 | ||
|  |       this.put(key, value); | ||
|  | 
 | ||
|  |       return value; | ||
|  |     } | ||
|  | 
 | ||
|  |     console.log(`Item not available in cache for key ${key}`); | ||
|  |   } | ||
|  | 
 | ||
|  |   ensureLimit(){ | ||
|  |     if(this.size === this.limit){ | ||
|  |       this.remove(this.tail.key) | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   remove(key){ | ||
|  |     const node = this.cache[key]; | ||
|  | 
 | ||
|  |     if(node.prev !== null){ | ||
|  |       node.prev.next = node.next; | ||
|  |     }else{ | ||
|  |       this.head = node.next; | ||
|  |     } | ||
|  | 
 | ||
|  |     if(node.next !== null){ | ||
|  |       node.next.prev = node.prev; | ||
|  |     }else{ | ||
|  |       this.tail = node.prev | ||
|  |     } | ||
|  | 
 | ||
|  |     delete this.cache[key]; | ||
|  |     this.size--; | ||
|  |   } | ||
|  | 
 | ||
|  |   clear() { | ||
|  |     this.head = null; | ||
|  |     this.tail = null; | ||
|  |     this.size = 0; | ||
|  |     this.cache = {}; | ||
|  |   } | ||
|  | 
 | ||
|  |   // // Invokes the callback function with every node of the chain and the index of the node.
 | ||
|  |   // forEach(fn) {
 | ||
|  |   //   let node = this.head;
 | ||
|  |   //   let counter = 0;
 | ||
|  |   //   while (node) {
 | ||
|  |   //     fn(node, counter);
 | ||
|  |   //     node = node.next;
 | ||
|  |   //     counter++;
 | ||
|  |   //   }
 | ||
|  |   // }
 | ||
|  | 
 | ||
|  |   // // To iterate over LRU with a 'for...of' loop
 | ||
|  |   // *[Symbol.iterator]() {
 | ||
|  |   //   let node = this.head;
 | ||
|  |   //   while (node) {
 | ||
|  |   //     yield node;
 | ||
|  |   //     node = node.next;
 | ||
|  |   //   }
 | ||
|  |   // }
 | ||
|  | } |