Reputation: 463
I currently have a simple search function implemented here that allows a user to search for courses. The user can input queries multiple queries separated by commas, and I am filtering the results if there exists a match to each tokenized query (done iteratively):
search($event) {
var re = /\s*,\s*/;
let splitQuery = this.searchText.split(re);
let numQueries = splitQuery.length;
let tempCourses = this.courses;
for (var i = 0;i < numQueries; i ++){
tempCourses = this.rankAndFilter(tempCourses, splitQuery[i].toUpperCase())
}
this.courseResults = this.sortByRank(tempCourses);
I would also like for all the queries to be highlighted in the search results as well, to be viewable to the user. This is the original highlight pipe and I have tried to modify it, but it doesn't return each individual word highlighted.
transform(value: string, args: string): any {
var re = /\s*,\s*/;
if (args && value){
let splitQuery = args.split(re);
let numQueries = splitQuery.length;
let returnedHighlighted: String = value;
console.log(`number of queries: ${numQueries}`)
for (var i = 0; i < numQueries; i++){
console.log(`${i}: ${splitQuery[i]}`)
let startIndex = value.toUpperCase().indexOf(splitQuery[i].toUpperCase());
if (startIndex != -1) {
let endLength = args.length;
let matchingString = value.substr(startIndex, endLength);
returnedHighlighted = returnedHighlighted.replace(matchingString, "<mark>" + matchingString + "</mark>");
}
}
return returnedHighlighted
}
return value; }
A test case would be the query linear algebra
returns 89A Statistics
and 54 Mathematics
, a query linear algebra, probability
returns both courses but with the individual words highlighted, and the query linear algebra, probability, data science
would only return 89A Statistics
with each individual query highlighted.
In reality this will be applied to over tens of thousands of courses, so any pointers / implementations for time efficiency for either the highlighting or filtering would also be appreciated.
Thank you!
Upvotes: 1
Views: 945
Reputation: 463
Building off @Eliseo's answer to handle edge cases such as "query," and "query, ":
transform(value: string, args: string): any {
if (args && value){
let re_noSpace = /\s*,\s*/;
let queryList = args.split(re_noSpace).filter(String);
let re_matchQueries = new RegExp(queryList.join('|'),"gi");
return value.replace(re_matchQueries,(x)=>"<mark>"+x+"</mark>");
}
return value;
}
Upvotes: 0
Reputation: 57971
You can do it in one step. Create a regExpresion that search the different values an replace by the < mark>value< /mark>
@Pipe({ name: 'highlight' })
export class HighlightPipe implements PipeTransform {
transform(value: string, args: string): any {
if (args && value){
var re = new RegExp(args.split(',').join('|'),"gi");
//e.g. if args was linear,equa, the regExpr will become /linear|equa/gi
return value.replace(re,(x)=>"<mark>"+x+"</mark>");
}
return value;
}
}
NOTE: You must check if use an especial characters $, ...
Upvotes: 3