Skip to content

Instantly share code, notes, and snippets.

@ManasJayanth
Created July 27, 2018 06:33
Show Gist options
  • Save ManasJayanth/612095d5bac98e7ec8c941c8bc7445a3 to your computer and use it in GitHub Desktop.
Save ManasJayanth/612095d5bac98e7ec8c941c8bc7445a3 to your computer and use it in GitHub Desktop.
Debalina - zipcode search with tries
const root = document.getElementById('root');
class TrieNode{
constructor(c) {
this.key = c;
this.parent = null;
this.children = {}; // Hash mapping character to next level
this.end = false; // End of node
this.data = null
}
getWord() {
var output = [];
var node = this;
// Traverse back to parent to generate the word
while (node !== null) {
output.unshift(node.key);
node = node.parent;
}
return output.join('');
}
}
class Trie {
constructor() {
this.root = new TrieNode(null);
}
// Inserts a word
insert(word, data) {
var node = this.root;
// for every character in the word
for(var i = 0; i < word.length; i++) {
// check to see if character node exists in children.
if (!node.children[word[i]]) {
// if it doesn't exist, we then create it.
node.children[word[i]] = new TrieNode(word[i]);
// we also assign the parent to the child node.
node.children[word[i]].parent = node;
}
// proceed to the next depth in the trie.
node = node.children[word[i]];
// finally, we check to see if it's the last word.
if (i == word.length-1) {
// if it is, we set the end flag to true.
node.data = node.data ? node.data.concat([data]): [ data ];
node.end = true;
}
}
}
// Check if it contains the word.
contains(word) {
var node = this.root;
// for every character in the word
for(var i = 0; i < word.length; i++) {
// check to see if character node exists in children.
if (node.children[word[i]]) {
// if it exists, proceed to the next depth of the trie.
node = node.children[word[i]];
} else {
// doesn't exist, return false since it's not a valid word.
return false;
}
}
// we finished going through all the words, but is it a whole word?
return node.end;
}
// returns all words with given prefix
find(prefix) {
var node = this.root;
var output = [];
// for every character in the prefix
for(var i = 0; i < prefix.length; i++) {
// make sure prefix actually has words
if (node.children[prefix[i]]) {
node = node.children[prefix[i]];
} else {
// there's none. just return it.
return output;
}
}
// recursively find all words in the node
findAllWords(node, output);
return output;
}
}
// recursive function to find all words in the given node.
function findAllWords(node, arr) {
if (node.end) {
arr.unshift({ word: node.getWord(), data: node.data });
}
// iterate through each children, call findAllWords
for (var child in node.children) {
findAllWords(node.children[child], arr);
}
}
// // insert few values
// // check contains method
// console.log(trie.contains("helium")); // true
// console.log(trie.contains("kickass")); // false
// // check find method
// console.log(trie.find("hel")); // [ 'helium', 'hello' ]
// console.log(trie.find("hell")); // [ 'hello' ]
function filter(nodeList, fn) {
return Array.prototype.filter.call(nodeList, fn);
}
function process(xmlDoc) {
var trie = new Trie();
const zipCodeNodes = filter(xmlDoc.children[0].childNodes, node => {
return node.nodeType === 1;
});
zipCodeNodes
// .slice(0, 10)
.forEach(node => {
const dataNodes = filter(node.childNodes, node => {
return node.nodeType === 1;
});
const code = dataNodes[0].childNodes[0].data;
const city = dataNodes[1].childNodes[0].data;
const state = dataNodes[2].childNodes[0].data;
trie.insert(city, { code, city, state });
})
root.innerHTML = searchUI();
}
root.innerHTML = '<div class"loading">Fetching and loading data...</div>';
fetch('/zipcode.xml').then(response => response.text())
.then(str => (new window.DOMParser()).parseFromString(str, "text/xml"))
.then(process)
.catch(console.error);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment