Search Part III: Contextual Search
Contextual search and optimizations
by rocketegg0
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.7/angular.min.js"></script>
<div ng-controller="MyCtrl">
<h2>Part 3: Contextual Search</h2>
<div>Search: <input type="text" ng-model="textIn"></input></div>
<div>Context (#)<input type="number" ng-model="context" value=1></input></div>
<div>
Typeahead Results:
<table>
<tr>
<th>Search Result:</th>
<th>Context</th>
</tr>
<tr ng-repeat="word in typeahead(textIn)">
<td>
{{word.value}}:{{word.position}}
</td>
<td><em>
{{dict.slice(word.position - context, word.position + context).join(' ')}}</em>
</td>
</tr>
</table>
</div>
</div>
CSS
h2 {
font-size: 150%;
}
table {
margin-top: 10px;
border: 1px solid #ccc;
width: 100%;
}
table th {
font-weight: bold;
}
em {
font-style: italic;
}
JavaScript
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl', function($scope, $q) {
// Compute NGrams
var computeNGrams = function(dict) {
$scope.dict = dict.split(' ');
return $scope.dict.reduce(ngramize, {});
};
// NGramize a word
function ngramize(hash, word, index) {
for (var i = 3; i < word.length+1; i++) {
var s = word.substring(i - 3, i);
if (!hash.hasOwnProperty(s)) {
hash[s] = [new Word(word, index)];
} else {
//todo, still eliminate dupes
hash[s].push(new Word(word, index));
}
}
return hash;
}
var merge = function(arrays) {
var returnArray = [];
if (!arrays) return [];
var base = arrays.pop();
var intersected = arrays.reduce(intersect, base);
return intersected;
};
$scope.typeahead = function(textIn) {
if (!textIn || textIn.length < 3) return [];
var ngrams = Object.keys(ngramize({}, textIn, 0));
return flatten(merge(ngrams.map(function(ngram) {
return $scope.hash[ngram] || [];
})));
};
$scope.hash = computeNGrams(dictionary);
$scope.context = 3;
});
// Word: has a string word and an int position
var Word = function(value, position) {
var self = this;
this.value = value;
this.position = position;
this.equals = function(word2) {
return self.value == word2.value && self.position == word2.position;
};
};
// Note: We can optimize this by using keeping arrays sorted
var intersect = function(array1, array2) {
var intersection = [];
array1.forEach(function(element1) {
array2.forEach(function(element2) {
if (element1.equals(element2)) {
intersection.push(element1);
}
});
});
return intersection;
};
// Some Array Helper Methods
var flatten = function(arrays)...