const arr = [
{label : 'lbl1', text: 'txt1'},
{label : 'lbl2', text: 'txt2'},
{label : 'lbl3', text: 'txt3'},
{label : 'lbl4', text: 'txt4'},
// much more items
];
const filterBy = [
{label: 'lbl1',text: 'txt1'},
{label : 'lbl4', text: 'txt4'}
//may have 0 or more items
];
I want to dynamically filter arr
by filterBy
. filterBy
is coming from the UI… here its just a representation of what the user can pass…
in a static way I would do:
arr.filter(x => (x.text == filterBy[0].text && x.label == filterBy[0].label) ||
. (x.text == filterBy[1].text && x.label == filterBy[1].label)
);
Is it possible to chain dynamic criterions in JS?
Thanks
6
You can easily achieve this result using filter and some
const arr = [
{ label: "lbl1", text: "txt1" },
{ label: "lbl2", text: "txt2" },
{ label: "lbl3", text: "txt3" },
{ label: "lbl4", text: "txt4" },
];
const filterBy = [
{ label: "lbl1", text: "txt1" },
{ label: "lbl4", text: "txt4" },
];
const result = arr.filter(({ label, text }) =>
filterBy.some((o) => o.label === label && o.text === text)
);
console.log(result);
0
You can use reduce and inside the callback use filter to get the items from arr
const arr = [{
label: 'lbl1',
text: 'txt1'
},
{
label: 'lbl2',
text: 'txt2'
},
{
label: 'lbl3',
text: 'txt3'
},
{
label: 'lbl4',
text: 'txt4'
},
//.... much more items
];
const filterBy = [{
label: 'lbl1',
text: 'txt1'
},
{
label: 'lbl4',
text: 'txt4'
}
];
const res = filterBy.reduce((acc, curr) => {
acc.push(...arr.filter(item => {
return item.label === curr.label && item.text === curr.text
}))
return acc;
}, []);
console.log(res)
use an obj instead of an array
const arr = [
{label : 'lbl1', text: 'txt1'},
{label : 'lbl2', text: 'txt2'},
{label : 'lbl3', text: 'txt3'},
{label : 'lbl4', text: 'txt4'},
];
const filterBy = {
criteria1:"lbl1",
criteria2:"txt1",
criteria3:"lbl4",
criteria4:"txt2",
}
const filtered = arr.filter(item => filterBy["criteria1"] === item.label ||filterBy["criteria2"] === item.text)||filterBy["criteria3"] === item.label || filterBy["criteria4"] === item.text);
the other “solutions” have to make two or plus loops. while this one only do one.
while more criterias you have, the uglier it is going to look like
const arr = [
{label : 'lbl1', text: 'txt1'},
{label : 'lbl2', text: 'txt2'},
{label : 'lbl3', text: 'txt3'},
{label : 'lbl4', text: 'txt4'},
// much more items
];
const filterBy = [
{label: 'lbl1',text: 'txt1'},
{label : 'lbl4', text: 'txt4'}
//may have 0 or more items
];
// If you want `||` between the filters.
console.log(arr.filter(x => filterBy.some(f => f.label === x.label && f.text === x.text)));
// If you want `&&` between the filters.
console.log(arr.filter(x => filterBy.every(f => f.label === x.label && f.text === x.text)));
I think this is what you wants.. dynamic criterias.. using Object.keys and reduce you can get this.
const arr = [
{label : 'lbl1', text: 'txt1'},
{label : 'lbl2', text: 'txt2'},
{label : 'lbl3', text: 'txt3'},
{label : 'lbl4', text: 'txt4'},
// much more items
];
const filterBy = [
{label: 'lbl1',text: 'txt1'},
{label : 'lbl4', text: 'txt4'}
];
const filtered = arr.filter(item => {
return filterBy.some(fItem => {
const keys = Object.keys(fItem);
return keys.length > 0 && keys.reduce((acc, k) => {
return acc && item[k] === fItem[k];
}, true)
});
});
console.log(filtered)