Skip to content

Instantly share code, notes, and snippets.

@Nephos
Last active July 9, 2020 12:38
Show Gist options
  • Save Nephos/436095a7c7a341ff8db53ba6fef62da6 to your computer and use it in GitHub Desktop.
Save Nephos/436095a7c7a341ff8db53ba6fef62da6 to your computer and use it in GitHub Desktop.
Damn
/**
* @example
* new SearchEngine(lines, { subfield: 'conditions' }).execute('key:value')
*/
class SearchEngine {
constructor(data, options = {}) {
this.data = data;
this.options = options;
}
parseString(query_rest, stop_chars = ' :') {
let stop = false, escape = false, quote = false, string = '';
while (stop === false && query_rest.length > 0) {
const char = query_rest[0];
query_rest = query_rest.slice(1, query_rest.length);
if (string.length === 0 && char === ' ') { // strip space before
// pass
} else if (escape === true) { // if escape, force the char
string += char;
escape = false;
} else if (quote && char === '"') { // if ending the last quote
quote = false;
} else if (!quote && char === '"') { // if starting a new quote
quote = true;
} else if (quote) { // if current quote active, accept every char
string += char;
} else if (stop_chars.indexOf(char) > -1) { // if we must stop the string
stop = true;
} else {
string += char;
}
}
return { query_rest, output: string };
}
parseQuery(query_rest = '') {
const parsed = [];
while (query_rest.length > 0) {
const key = this.parseString(query_rest);
const value = this.parseString(key.query_rest);
parsed.push([key.output, value.output]);
query_rest = value.query_rest;
}
return parsed;
}
execute(query) {
// const parsed_search = query.split(' ').map(e => e.split(':')); // [ [ k, v], [ k, v ] ]
const parsed_search = this.parseQuery(query);
return this.data.filter((line) => {
try {
return this.privateExecuteOnLine(parsed_search, line);
} catch (err) {
console.log(err, line.conditions, parsed_search);
}
return false;
});
}
/**
* The line may be:
* a string "..."
* an array of object [ { ... }, ...]
* an object { ... }
*
* Each type of line has its own search implementation
*
*/
privateExecuteOnLine(parsed_search, line) {
const effective_line = this.options.subfield ? line[this.options.subfield] : line;
if (effective_line instanceof String) {
return parsed_search.reduce((b, p) => b && effective_line.indexOf(p), true);
} else if (effective_line instanceof Array && effective_line[0] instanceof Object) {
return parsed_search.reduce((b, p) => b && effective_line.find(cond => cond[p[0]] && cond[p[0]].indexOf(p[1]) > -1), true);
} else if (effective_line instanceof Object) {
return parsed_search.reduce((b, p) => b && effective_line[p[0]] && effective_line[p[0]].indexOf(p[1]) > -1, true);
}
return false;
}
}
module.exports = SearchEngine;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment