I have an array which is constructed using user input values and can have any length:
var products = [
{key1: string1,
key2: 1,
key3: 30,
key4: 1},
{key1: string2,
key2: 2,
key3: 35,
key4: 2}
]
And I have some filters
var filters = {
key2: 1,
key3: {min: 20, max: 40},
key4: 1,
}
I'm currently using the below function to filter products using my filters
function multiFilter(array, filters) {
const filterKeys = Object.keys(filters);
return array.filter((item) => {
// flipped around, and item[key] forced to a string
return filterKeys.every(key => !!~String(item[key]).indexOf(filters[key]));
});
}
var filtered = multiFilter(products, filters);
console.log(filtered);
Everything works as expected when key3 in filters has an exact number, but I'm running into issues when trying to incorporate a range. How would I amend the function to allow for a range in key3 (filters)?
Maybe this approach would be useful
const products = [
{key1: 'string0',key2: 0,key3: 10,key4: 1},
{key1: 'string1',key2: 1,key3: 15,key4: 1},
{key1: 'string2',key2: 2,key3: 20,key4: 1},
{key1: 'string3',key2: 3,key3: 25,key4: 2},
{key1: 'string4',key2: 4,key3: 30,key4: 2},
{key1: 'string5',key2: 5,key3: 35,key4: 2},
{key1: 'string6',key2: 6,key3: 40,key4: 4},
{key1: 'string7',key2: 7,key3: 45,key4: 4},
{key1: 'string8',key2: 8,key3: 50,key4: 4},
{key1: 'string9',key2: 9,key3: 55,key4: 4}];
const filters = {
key2: {max: 7},
key3: {min: 20, max: 60},
key4: 4,
};
const filterProdacts = (products, filters) => {
// First, we create an object where the property values (min, max, eq)
// are predicate functions.
const fns = {
eq: (key, value) => (obj) => obj[key] === value,
min: (key, value) => (obj) => obj[key] >= value,
max: (key, value) => (obj) => obj[key] <= value,
};
// Generates a predicate based on the conditions
makePredicat = (filterKey, filterValue) => {
// For consistency мake the numeric values as an object like { eq: 5 }
const filterObj = (typeof filterValue === 'object')
? filterValue
: { eq: filterValue };
// Pick a function from fns and initialize it with the condition parameters
return Object.entries(filterObj)
.map(([condKey, condValue]) => fns[condKey](filterKey, condValue));
};
// Fill in the array with predicate functions for each condition.
// In this example there will be 4 functions, one for each condition
// key2 - max: 7; key3 - min: 20; key3 - max: 60; key4 - eq: 4;
const predicats = Object.entries(filters).flatMap(([key, value]) => makePredicat(key, value));
// Initializing reduce by source array
// then filtering it with all predicate functions
return predicats.reduce((acc, fn) => acc.filter(fn), products);
};
console.log(filterProdacts(products, filters));
.as-console-wrapper{min-height: 100%!important; top: 0}