Skip to content

Instantly share code, notes, and snippets.

@paceaux
Last active June 5, 2020 16:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save paceaux/11c5b06d16abba4d45571e1d10174938 to your computer and use it in GitHub Desktop.
Save paceaux/11c5b06d16abba4d45571e1d10174938 to your computer and use it in GitHub Desktop.
SearchMap: A JavaScript Map with searchable keys
/** Evaluates an array, makes the key lowercasee and makes the value an object with original keyname
* @param {Array} iterable=[] an array of arrays:[[key,val],[key,val]]
* @returns Array
*/
function LowercaseIterable(iterable = []) {
if (iterable.length === 0) return [];
const newIterable = iterable.map(([key, val]) => {
const entry = [
key.toLowerCase(),
{ originalKeyName: key, value: val }
];
return entry;
});
return newIterable;
}
/**
* @extends Map
* @classdesc Makes it possible to do a case insensitive search of a map by key
* @namespace SearchableKeyMap
* @property {Map} originalMap the original, unchanged map
*/
class SearchableKeyMap extends Map {
/**
* @param {Iterable} iterable an array of arrays: [[key,val], [key,val]]
*/
constructor(iterable) {
super(LowercaseIterable(iterable));
this.originalMap = new Map(iterable);
}
/** Determines if any of SearchableKeyMap's keys contain a substring
* @param {string} searchKey
*
* @returns {Boolean}
*/
containsKey(searchKey) {
const searchKeyName = searchKey.toLowerCase();
const entries = this.entries();
let result = false;
let nextEntry = entries.next();
while (!nextEntry.done) {
const key = nextEntry.value[0];
if (key.includes(searchKeyName)) {
result = true;
break;
}
nextEntry = entries.next();
}
return result;
}
/** Searches in a map for a single key containing a substring
* @param {string} searchKey
*
* @returns string. First result it finds
*/
getKeyContaining(searchKey) {
const searchKeyName = searchKey.toLowerCase();
const entries = this.entries();
let result;
let nextEntry = entries.next();
while (!nextEntry.done) {
const [key] = nextEntry.value;
if (key.includes(searchKeyName)) {
result = key;
break;
}
nextEntry = entries.next();
}
return result;
}
/** Searches for keys in a map that contain a substring *
* @param {string} searchKey
*
* @returns array
*/
getKeysContaining(searchKey) {
const result = [];
const searchKeyName = searchKey.toLowerCase();
const entries = this.entries();
let nextEntry = entries.next();
while (!nextEntry.done) {
const [key] = nextEntry.value;
if (key.includes(searchKeyName)) {
result.push(key);
}
nextEntry = entries.next();
}
return result;
}
/** Creates a SearchableKeyMap of keys based on a search string
* @param {string} keyName key to search for
*
* @returns SearchableKeyMap
*/
mapFromKeysContaining(keyName) {
if (!keyName) throw new Error('Keyname not provided');
const newMap = new SearchableKeyMap();
const searchKeyName = keyName.toLowerCase();
const keys = this.getKeysContaining(searchKeyName);
keys.forEach((key) => {
const { originalKeyName, value } = this.get(key);
newMap.set(originalKeyName, value);
});
return newMap;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment