Применить переменное число условий фильтра к массиву JavaScript, обходя его только один раз? - PullRequest
3 голосов
/ 22 октября 2019

У меня есть массив javascript вложенных данных, в котором хранятся данные, которые будут отображаться пользователю.

Пользователь хотел бы иметь возможность применять условия фильтрации 0 к n к данным, которые они просматривают.

Для достижения этой цели мне нужно сначала найти элементы, которые соответствуют условиям фильтрации от 0 до n, а затем выполнить некоторые манипуляции с данными для этих записей. Очевидный способ решения этой проблемы состоит в том, чтобы иметь несколько операторов фильтра вплотную (с условной проверкой внутри них, чтобы увидеть, нужно ли применять фильтр), а затем функцию карты в конце, например:

var firstFilterList = _.filter(myData, firstFilterFunction);
var secondFilterList = _.filter(firstFilterList, secondFilterFunction);
var thirdFilterList = _.filter(secondFilterList, thirdFilterFunction);
var finalList = _.map(thirdFilterList, postFilterFunction);

В этом случае, однако, массив javascript будет проходиться 4 раза. Чтобы обойти это, можно использовать один фильтр, который проверяет все 3 (или от 0 до n) условия, прежде чем определять, есть ли совпадение, а затем внутри фильтра в конце функции выполняет манипулирование данными,однако это кажется немного странным и делает «фильтр» ответственным за более чем одну вещь, что не идеально. Положительным моментом было бы то, что javascript Array просматривается только один раз.

Есть ли способ «наилучшей практики» для выполнения того, чего я пытаюсь достичь?

РЕДАКТИРОВАТЬ: Мне также интересно слышатьесли считается неправильным выполнять манипуляции с данными (добавление полей к объектам javascript и т. д.) в функции фильтра.

Ответы [ 2 ]

3 голосов
/ 22 октября 2019

Вы можете собрать все функции фильтра в массив и проверить каждый фильтр с фактическим набором данных и фильтровать по результату. Затем возьмите свою функцию отображения, чтобы получить желаемый результат.

var data = [ /* ... */ ],
    filterFn1 = () => Math.round(Math.random()),
    filterFn2 = (age) => age > 35,
    filterFn3 = year => year === 1955,
    fns = [filterFn1, filterFn2, filterFn2],
    whatever = ... // final function for mapping
    result = data
        .filter(x => fns.every(f => f(x)))
        .map(whatever);
2 голосов
/ 22 октября 2019

Одна вещь, которую вы можете сделать, это объединить все эти функции фильтра в одну функцию с reduce, затем вызвать filter с объединенной функцией.

var combined = [firstFilterFunction, seconfFilterFunction, ...]
                .reduce((x, y) => (z => x(z) && y(z)));
var filtered = myData.filter(combined);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...