I\'m wondering what is the cleanest way, better way to filter an array of objects depending on a string keyword. The search has to be made in any properties of
This code checks all the nested values until it finds what it's looking for, then stops and returns true to the "array.filter" for the object it was searching inside(unless it can't find anything - returns false). When true is returned, the object is added to the array that the "array.filter" method returns.
const data = [{
a: "a",
b: {
c: "c",
d: {
e: "e",
f: [
"g",
{
i: "i",
j: {},
k: []
}
]
}
}
},
{
a: "a",
b: {
c: "c",
d: {
e: "e",
f: [
"g",
{
i: "findme",
j: {},
k: []
}
]
}
}
},
{
a: "a",
b: {
c: "c",
d: {
e: "e",
f: [
"g",
{
i: "i",
j: {},
k: []
}
]
}
}
}
];
function getState(data: any, inputValue: string, state = false) {
for (const value of Object.values(data)) {
if (typeof value === 'object' && value !== null && Object.keys(value).length > 0 && state === false) {
state = getState(value, inputValue, state);
} else {
if (state === false) {
state = JSON.stringify(value).toLowerCase().includes(inputValue.toLowerCase());
} else {
return state;
}
}
}
return state;
}
function filter(data: [], inputValue) {
return data.filter((element) => getState(element, inputValue));
}
console.log(filter(data, 'findme'));
If you need to search for objects that contain multiple keywords, to narrow down the filtered objects further, which makes the filter even more user friendly.
const data = [{
a: "a",
b: {
c: "c",
d: {
e: "findme2",
f: [
"g",
{
i: "i",
j: {},
k: []
}
]
}
}
},
{
a: "a",
b: {
c: "c",
d: {
e: "e",
f: [
"g",
{
i: "findme",
j: {},
k: []
}
]
}
}
},
{
a: "a",
b: {
c: "c",
d: {
e: "findme2",
f: [
"g",
{
i: "findme",
j: {},
k: []
}
]
}
}
}
];
function filter(data: [], inputValue: string) {
return data.filter((element) => checkState(element, inputValue));
}
function checkState(element: any, inputValue: string) {
const filterValues = inputValue.trim().split(' ');
const states: boolean[] = [];
for (let index = 0; index < filterValues.length; index++) {
states[index] = getState(element, filterValues[index]);
}
return states.every(state => state === true);
}
function getState(data: any, inputValue: string, state = false) {
for (const value of Object.values(data)) {
if (typeof value === 'object' && value !== null && Object.keys(value).length > 0 && state === false) {
state = getState(value, inputValue, state);
} else {
if (state === false) {
state = JSON.stringify(value).toLowerCase().includes(inputValue.toLowerCase());
} else {
return state;
}
}
}
return state;
}
console.log(filter(data, 'findme')); // gets all objects that contain "findme"
console.log(filter(data, 'findme findme2')); // gets all objects that contain "findme" and "findme2"