我目前正在编写一个类来过滤数组中的对象。此类的内部方法之一需要进行测试,以查看特定属性是否满足数组中传递的任何“范围”。
考虑以下过滤器对象:
const filters = {
duration: ['<30', '>30<60', '>300<900', '>900<1800', '>1800', '>60<300']
};
现在考虑以下项数组(和对象):
const items = [
{
duration: 10
},
{
duration: 500
},
{
duration: 10000
}
];
我需要编写一个函数,该函数将动态生成将items[x].duration
的值与filters.duration
中定义的每个范围进行比较的测试。
以上述数据为例,预期结果将是:
[
{
duration: 10
},
{
duration: 500
}
];
我已经有了应用过滤器的逻辑。这是我到目前为止所拥有的:
/**
* 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
}
对此进行更多思考,我认为最好的方法是从提供的范围字符串中提取范围并返回一个对象,如下所示:
{
min: 0,
max: 0
}
考虑到这一点,_rangeHelper
应该返回以下内容:
对于<20
:
{
max: 20
}
对于<1800
:
{
min: 1800
}
对于>60<300
:
{
min: 60,
max: 300
}
我认为这样就可以相当简单地使用range.min
和range.max
值在范围之间进行测试。
很快就会回答我自己的问题而感到内...……尽管仍然很想听听其他想法。这是我的最新更新:
/**
* 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
};
}
答案 0 :(得分:2)
考虑一下:
let value = 70;
let filters = ['<30', '>30<60', '>300<900', '>900<1800', '>1800', '>60<300'];
function matchRange(value, range){
const edges = range.match(/[\<\>]\d*/g);
return edges.every(edge => {
const [, comp, num] = edge.match(/([\<\>])(\d*)/);
return comp == '>' ? value > Number(num) : value < Number(num);
})
}
filters.some( range => matchRange( value, range ) );