I am currently writing a class to filter objects within an array. One of the internal methods of this class needs to test to see if a specific property satisfies any of the 'ranges' passed in an array.
Consider the following filter object:
const filters = {
duration: ['<30', '>30<60', '>300<900', '>900<1800', '>1800', '>60<300']
};
Now consider the following items array (and objects):
const items = [
{
duration: 10
},
{
duration: 500
},
{
duration: 10000
}
];
I need to write a function that will dynamically generate the tests that will compare the value of items[x].duration to each of the ranges defined in filters.duration.
Using the above data as an example, the expected result would be:
[
{
duration: 10
},
{
duration: 500
}
];
I already have the logic for applying the filters. This is what I have so far:
/**
* Filter the item by duration.
*
* @param {object} item
* @param {array} values
* @returns {boolean}
*/
_filterByDuration(item, values) {
// NOTES FOR SO:
// `item` represents the item to test
// `values` represents the supplied range e.g. ['<30', '>1800', '>60<300']
// If any of them match then return `true`
return values.some( range => {
range = this._rangeHelper(range);
// Stuck here...
// Need to test `item.duration` against the `range` values
});
}
/**
* Extract a testable range from the supplied string.
*
* @param {string} range
* @returns {object}
*/
_rangeHelper(range) {
// Can't decide whether to return an object/array
// Most likely need a regex to build the dynamic
// range
}
Update 1
Thinking more about this, I think the best method is to extract the range from the supplied range strings and return an object like so:
{
min: 0,
max: 0
}
With this in mind, _rangeHelper should return the following:
For <20:
{
max: 20
}
For <1800:
{
min: 1800
}
For >60<300:
{
min: 60,
max: 300
}
I think this will then make it fairly simply to just test between the ranges using the range.min and range.max values.
Update 2
Might be guilty of answering my own question shortly... Still keen to hear other ideas though. This is my latest update:
/**
* Extract a testable range from the supplied string.
*
* @param {string} range
* @returns {object}
*/
_rangeHelper(range) {
const min = range.match(/>(\d+)/);
const max = range.match(/<(\d+)/);
return {
min: min && typeof min[1] !== 'undefined' ? min[1] : null,
max: max && typeof max[1] !== 'undefined' ? max[1] : null
};
}
const filters = [ (x) => x < 60, (x) => x < 50 && x > 100]I've just made up some functions here but you could put anything you like in those functions