I have a situation, where I need to filter an array using dynamic filter (and sometimes also complex filter criteria).
I have extended the Array class to add a method for this. This works fine, as long as I can specify straightforward filter criteria like {gender: "m"} and I can of course and some of these criteria.
What I would like to do in addition, though, is to specify more complex filter criteria, basically a dynamic callback function for the Array.prototype.filter() method. I can get this to work with eval(), but the performance is horrible and "Don't use eval()" is written all over the internet.
Do you have any suggestions how to solve this? Any suggestion to safely and efficiently pre-compile the complex filter string like ("key1==key2 || (last=="Smith" && gender=="m")
<script>
var People = [
{ first: 'Peter', last: 'Henderson', key1:0, gender: "m", key2:0 },
{ first: 'Paul', last: 'Paulson', key1: 10, gender: "m", key2:10 },
{ first: 'Mary', last: 'Miller', key1: 2, gender: "f", key2:0 },
{ first: 'Mary', last: 'Smith', key1: 3 , gender: "f" , key2:3 },
{ first: 'Peter', last: 'Smith' , key1: 4, gender: "m", key2:0 }
];
console.log(People);
var newPeople = MyArray.from(People).filterBy("@key1 == @key2");
console.log(newPeople);
newPeople = MyArray.from(People).filterBy({gender: "m", last:"Smith"});
console.log(newPeople);
</script>
classs MyArray extends Array {
filterBy(argument) {
return this.filter(function(el){
if (typeof argument == "object") {
// object with key/parameter pairs for filtering:
// {key1: 0, gender: "m"}
for (let key in argument) {
if (argument[key] !== el[key]) return false;
};
return true;
} else if (typeof argument == "string") {
// string with logical expression with key names @-escaped, e.g.
// @gender == 'm' && @key1 == @key2
let expression = argument.split("@").join("el.")
return eval(expression);
}
});
}
}
People.filter(person => person.key1 === person.key2 || (person.last === "Smith" && person.gender === "m"));? Why do you need an entire extension toArrayfor something that's already there?A -> Boolean, whereAis the type of elements in the array. Then you can pass this function into the standardfiltermethod to obtain an appropriately filtered array.person.key1 === person.key2 || (person.last === "Smith" && person.gender === "m")would have to be dynamic. Can I build it as avarand hand it over to the .filter method?