I'm basically trying to implement a search for any given value should look in the array of object key values(there can also be nested objects). Here is an example. The below function will take an object and a query to search in array objects key values. So, if a match is found it should filter from that array.
function searchObj (obj, query) {
for (var key in obj) {
var value = obj[key];
if (typeof value === 'object') {
searchObj(value, query);
}
if (typeof value === 'string' && value.toLowerCase().indexOf(query.toLowerCase()) > -1) {
return obj;
}
}
}
here is the dummy data
var demoData=[
{id:1,desc:{original:'trans1'},date:'2017-07-16'},
{id:2,desc:{original:'trans2'},date:'2017-07-12'},
{id:3,desc:{original:'trans3'},date:'2017-07-11'},
{id:4,desc:{original:'trans4'},date:'2017-07-15'}
];
here is the array I'm filtering object of the match
var searchFilter = demoData.filter(function(obj){
return searchObj(obj, 'trans1');
});
console.log(searchFilter);
for example: if I call searchObj(obj,'2017-07-15') it returns that particular object but if I search for trans1 or simply trans it should look into the object and then return the match. I'm kinda stuck now any help would be appreciated. Thanks.
2 Answers 2
Case 1 is working because you are not hitting the recursion. But in case 2, you are keep searching even after found the result.
return the object once you find.
if (typeof value === 'object') {
return searchObj(value, query);
}
if (typeof value === 'string' && value.toLowerCase().indexOf(query.toLowerCase()) > -1) {
return obj;
}
function searchObj (obj, query) {
for (var key in obj) {
var value = obj[key];
if (typeof value === 'object') {
return searchObj(value, query);
}
if (typeof value === 'string' && value.toLowerCase().indexOf(query.toLowerCase()) > -1) {
return obj;
}
}
}
var demoData=[
{id:1,desc:{original:'trans1'},date:'2017-07-16'},
{id:2,desc:{original:'trans2'},date:'2017-07-12'},
{id:3,desc:{original:'trans3'},date:'2017-07-11'},
{id:4,desc:{original:'trans4'},date:'2017-07-15'}
];
var searchFilter = demoData.filter(function(obj){
return searchObj(obj, 'trans1');
});
console.log(searchFilter);
2 Comments
Another way to look at this is to just use JSON.stringify and search within that:
searchObj(obj, string) {
const regExpFlags = 'gi',
regExp = new RegExp(string, regExpFlags);
return JSON.stringify(obj).match(regExp);
}
And then test the search pattern:
var searchFilter = demoData.filter(function(obj){
return searchObj(obj, 'trans1');
});
console.log(searchFilter);
You can even go further and implement a loose search by providing an array of strings:
searchObj(obj, string) {
const jsonString = JSON.stringify(obj);
regExpFlags = 'gi',
regExpArray = string.split(' ');
testArray = [];
regExpArray.forEach(term => {
let regExp = new RegExp(term, regExpFlags);
if (jsonString.match(regExp) {
testArray.push(term);
}
});
return regExpArray.length === testArray.length;
}
I modified the data:
var demoData=[
{id:1,desc:{original:'trans1'},date:'2017-07-16'},
{id:1,desc:{original:'trans2'},date:'2017-07-12'},
{id:1,desc:{original:'trans3'},date:'2017-07-13'},
{id:2,desc:{original:'trans4'},date:'2017-07-12'},
{id:3,desc:{original:'trans5'},date:'2017-07-12'},
{id:4,desc:{original:'trans6'},date:'2017-07-15'},
{id:1,desc:{original:'trans7'},date:'2017-07-12'}
];
And the search term:
var searchFilter = demoData.filter(function(obj){
return searchObj(obj, 'trans 2017年07月12日');
});
console.log(searchFilter);
One important thing to note here is the performance of JSON.stringify, so this worked fine for me in a case with a limited number of deep nested objects (<1000).
Probably someone with more experience can shed some light on this.
return. You need to return the result of the recursive call.