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.
		
		
		
		
		
			
		
			
				
					197 lines
				
				4.5 KiB
			
		
		
			
		
	
	
					197 lines
				
				4.5 KiB
			| 
											3 years ago
										 | /** | ||
|  |  * Mnemonist FuzzyMultiMap | ||
|  |  * ======================== | ||
|  |  * | ||
|  |  * Same as the fuzzy map but relying on a MultiMap rather than a Map. | ||
|  |  */ | ||
|  | var MultiMap = require('./multi-map.js'), | ||
|  |     forEach = require('obliterator/foreach'); | ||
|  | 
 | ||
|  | var identity = function(x) { | ||
|  |   return x; | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * FuzzyMultiMap. | ||
|  |  * | ||
|  |  * @constructor | ||
|  |  * @param {array|function} descriptor - Hash functions descriptor. | ||
|  |  * @param {function}       Container  - Container to use. | ||
|  |  */ | ||
|  | function FuzzyMultiMap(descriptor, Container) { | ||
|  |   this.items = new MultiMap(Container); | ||
|  |   this.clear(); | ||
|  | 
 | ||
|  |   if (Array.isArray(descriptor)) { | ||
|  |     this.writeHashFunction = descriptor[0]; | ||
|  |     this.readHashFunction = descriptor[1]; | ||
|  |   } | ||
|  |   else { | ||
|  |     this.writeHashFunction = descriptor; | ||
|  |     this.readHashFunction = descriptor; | ||
|  |   } | ||
|  | 
 | ||
|  |   if (!this.writeHashFunction) | ||
|  |     this.writeHashFunction = identity; | ||
|  |   if (!this.readHashFunction) | ||
|  |     this.readHashFunction = identity; | ||
|  | 
 | ||
|  |   if (typeof this.writeHashFunction !== 'function') | ||
|  |     throw new Error('mnemonist/FuzzyMultiMap.constructor: invalid hash function given.'); | ||
|  | 
 | ||
|  |   if (typeof this.readHashFunction !== 'function') | ||
|  |     throw new Error('mnemonist/FuzzyMultiMap.constructor: invalid hash function given.'); | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Method used to clear the structure. | ||
|  |  * | ||
|  |  * @return {undefined} | ||
|  |  */ | ||
|  | FuzzyMultiMap.prototype.clear = function() { | ||
|  |   this.items.clear(); | ||
|  | 
 | ||
|  |   // Properties
 | ||
|  |   this.size = 0; | ||
|  |   this.dimension = 0; | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Method used to add an item to the index. | ||
|  |  * | ||
|  |  * @param  {any} item - Item to add. | ||
|  |  * @return {FuzzyMultiMap} | ||
|  |  */ | ||
|  | FuzzyMultiMap.prototype.add = function(item) { | ||
|  |   var key = this.writeHashFunction(item); | ||
|  | 
 | ||
|  |   this.items.set(key, item); | ||
|  |   this.size = this.items.size; | ||
|  |   this.dimension = this.items.dimension; | ||
|  | 
 | ||
|  |   return this; | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Method used to set an item in the index using the given key. | ||
|  |  * | ||
|  |  * @param  {any} key  - Key to use. | ||
|  |  * @param  {any} item - Item to add. | ||
|  |  * @return {FuzzyMultiMap} | ||
|  |  */ | ||
|  | FuzzyMultiMap.prototype.set = function(key, item) { | ||
|  |   key = this.writeHashFunction(key); | ||
|  | 
 | ||
|  |   this.items.set(key, item); | ||
|  |   this.size = this.items.size; | ||
|  |   this.dimension = this.items.dimension; | ||
|  | 
 | ||
|  |   return this; | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Method used to retrieve an item from the index. | ||
|  |  * | ||
|  |  * @param  {any} key - Key to use. | ||
|  |  * @return {any} | ||
|  |  */ | ||
|  | FuzzyMultiMap.prototype.get = function(key) { | ||
|  |   key = this.readHashFunction(key); | ||
|  | 
 | ||
|  |   return this.items.get(key); | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Method used to test the existence of an item in the map. | ||
|  |  * | ||
|  |  * @param  {any} key - Key to check. | ||
|  |  * @return {boolean} | ||
|  |  */ | ||
|  | FuzzyMultiMap.prototype.has = function(key) { | ||
|  |   key = this.readHashFunction(key); | ||
|  | 
 | ||
|  |   return this.items.has(key); | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Method used to iterate over each of the index's values. | ||
|  |  * | ||
|  |  * @param  {function}  callback - Function to call for each item. | ||
|  |  * @param  {object}    scope    - Optional scope. | ||
|  |  * @return {undefined} | ||
|  |  */ | ||
|  | FuzzyMultiMap.prototype.forEach = function(callback, scope) { | ||
|  |   scope = arguments.length > 1 ? scope : this; | ||
|  | 
 | ||
|  |   this.items.forEach(function(value) { | ||
|  |     callback.call(scope, value, value); | ||
|  |   }); | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Method returning an iterator over the index's values. | ||
|  |  * | ||
|  |  * @return {FuzzyMultiMapIterator} | ||
|  |  */ | ||
|  | FuzzyMultiMap.prototype.values = function() { | ||
|  |   return this.items.values(); | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Attaching the #.values method to Symbol.iterator if possible. | ||
|  |  */ | ||
|  | if (typeof Symbol !== 'undefined') | ||
|  |   FuzzyMultiMap.prototype[Symbol.iterator] = FuzzyMultiMap.prototype.values; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Convenience known method. | ||
|  |  */ | ||
|  | FuzzyMultiMap.prototype.inspect = function() { | ||
|  |   var array = Array.from(this); | ||
|  | 
 | ||
|  |   Object.defineProperty(array, 'constructor', { | ||
|  |     value: FuzzyMultiMap, | ||
|  |     enumerable: false | ||
|  |   }); | ||
|  | 
 | ||
|  |   return array; | ||
|  | }; | ||
|  | 
 | ||
|  | if (typeof Symbol !== 'undefined') | ||
|  |   FuzzyMultiMap.prototype[Symbol.for('nodejs.util.inspect.custom')] = FuzzyMultiMap.prototype.inspect; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Static @.from function taking an arbitrary iterable & converting it into | ||
|  |  * a structure. | ||
|  |  * | ||
|  |  * @param  {Iterable}       iterable   - Target iterable. | ||
|  |  * @param  {array|function} descriptor - Hash functions descriptor. | ||
|  |  * @param  {function}       Container  - Container to use. | ||
|  |  * @param  {boolean}        useSet     - Whether to use #.set or #.add | ||
|  |  * @return {FuzzyMultiMap} | ||
|  |  */ | ||
|  | FuzzyMultiMap.from = function(iterable, descriptor, Container, useSet) { | ||
|  |   if (arguments.length === 3) { | ||
|  |     if (typeof Container === 'boolean') { | ||
|  |       useSet = Container; | ||
|  |       Container = Array; | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   var map = new FuzzyMultiMap(descriptor, Container); | ||
|  | 
 | ||
|  |   forEach(iterable, function(value, key) { | ||
|  |     if (useSet) | ||
|  |       map.set(key, value); | ||
|  |     else | ||
|  |       map.add(value); | ||
|  |   }); | ||
|  | 
 | ||
|  |   return map; | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Exporting. | ||
|  |  */ | ||
|  | module.exports = FuzzyMultiMap; |