Динамически фильтровать массив объектов на основе массива диапазонов - PullRequest
0 голосов
/ 18 июня 2020

В настоящее время я пишу класс для фильтрации объектов в массиве. Один из внутренних методов этого класса должен проверить, удовлетворяет ли указанное свойство c любому из «диапазонов», переданных в массиве.

Рассмотрим следующий объект фильтра:

const filters = {
    duration: ['<30', '>30<60', '>300<900', '>900<1800', '>1800', '>60<300']
};

Теперь рассмотрим следующий массив элементов (и объекты):

const items = [
    {
        duration: 10
    },
    {
        duration: 500
    },
    {
        duration: 10000
    }
];

Мне нужно написать функцию, которая будет динамически генерировать тесты, которые будут сравнивать значение items[x].duration с каждым из определенных диапазонов in filters.duration.

Используя приведенные выше данные в качестве примера, ожидаемый результат будет:

[
    {
        duration: 10
    },
    {
        duration: 500
    }
];

У меня уже есть logi c для применения фильтров. Вот что у меня есть на данный момент:

/**
 * 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

}

Обновление 1

Подумав об этом подробнее, я думаю, что лучший метод - извлечь диапазон из предоставленных строк диапазона и вернуть такой объект, как так:

{
    min: 0,
    max: 0
}

Имея это в виду, _rangeHelper должен вернуть следующее:

For <20:

{
    max: 20
}

For <1800:

{
    min: 1800
}

Для >60<300:

{
    min: 60,
    max: 300
}

Я думаю, это упростит простое тестирование между диапазонами с использованием значений range.min и range.max.

Обновление 2

Возможно, я виноват в том, что вскоре отвечу на мой собственный вопрос ... Тем не менее, все еще очень хочу услышать другие идеи. Это мое последнее обновление:

/**
 * 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
    };

}

1 Ответ

2 голосов
/ 18 июня 2020

Рассмотрим это:

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 ) );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...