Created
May 7, 2017 02:52
-
-
Save AugmentedFifth/5f48bea2d3a15049b9b441ab105e49d5 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
function Trie(valueCons, hasValue=false) { | |
"use strict"; | |
const constructorFailure = new TypeError( | |
"Tries must be initialized with a valid constructor " + | |
"of an iterable type as the first argument." | |
); | |
if (typeof valueCons !== "function") { | |
throw constructorFailure; | |
} | |
try { | |
const val = new valueCons(); | |
if (typeof val[Symbol.iterator] !== "function") { | |
throw 0; | |
} | |
} catch (_) { | |
throw constructorFailure; | |
} | |
this.hasValue = hasValue; | |
this.children = new Map(); | |
this.valueCons = valueCons; | |
this.setValue = function(hasValue) { | |
this.hasValue = hasValue; | |
}; | |
this.hasChild = function(elem) { | |
return this.children.has(elem); | |
}; | |
this.getChild = function(elem) { | |
return this.children.get(elem); | |
}; | |
this.addChild = function(elem, child) { | |
this.children.set(elem, child); | |
}; | |
this.add = function(newVal) { | |
if ( | |
!( | |
newVal instanceof valueCons || | |
valueCons === String && typeof newVal === "string" | |
) | |
) { | |
throw new TypeError( | |
"Attempted to add a value of mismatched type to Trie.\n" + | |
"Expected type: " + | |
this.valueCons + | |
"\nGot this value: " + | |
newVal | |
); | |
} | |
let node = this; | |
for (const elem of newVal) { | |
if (node.hasChild(elem)) { | |
node = node.getChild(elem); | |
} else { | |
const newChild = new Trie(this.valueCons); | |
node.addChild(elem, newChild); | |
node = newChild; | |
} | |
} | |
node.setValue(true); | |
}; | |
this.allValues = function() { | |
const values = []; | |
if (this.hasValue) { | |
values.push(new valueCons()); | |
} | |
this.children.forEach((child, elem) => { | |
child.allValues().forEach(childVal => { | |
values.push(elem.concat(childVal)); | |
}); | |
}); | |
return values; | |
}; | |
this.contains = function(needle) { | |
if ( | |
!( | |
needle instanceof valueCons || | |
valueCons === String && typeof needle === "string" | |
) | |
) { | |
throw new TypeError( | |
"Attempted to search for a value of mismatched type in a Trie.\n" + | |
"Expected type: " + | |
this.valueCons + | |
"\nGot this value: " + | |
needle | |
); | |
} | |
let node = this; | |
for (const elem of needle) { | |
if (!node.hasChild(elem)) { | |
return false; | |
} | |
node = node.getChild(elem); | |
} | |
return node.hasValue; | |
}; | |
this.getPrefixCompletions = function(prefix) { | |
if ( | |
!( | |
prefix instanceof valueCons || | |
valueCons === String && typeof prefix === "string" | |
) | |
) { | |
throw new TypeError( | |
"Attempted to get completions for prefix of mismatched type in Trie.\n" + | |
"Expected type: " + | |
this.valueCons + | |
"\nGot this value: " + | |
prefix | |
); | |
} | |
let node = this; | |
for (const elem of prefix) { | |
node = node.getChild(elem); | |
if (!node) { | |
return []; | |
} | |
} | |
return node.allValues(); | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment