Отображение карри-фильтра с использованием функций lodash - PullRequest
4 голосов
/ 30 октября 2019

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

Используя lodash, я определяю:

const { curryRight, filter, flowRight } = require('lodash');

const curriedFilter = curryRight(filter);
const filterFromPredicates = (predicateList) => flowRight(...predicateList.map(curriedFilter));

Но это дает неправильный ответ:

const filter = filterFromPredicates([(x) => x > 2, (x) => x > 4])
filter([1,2,3,4,5,6,7,8,9]) // -> [1,2,3,4,5,6,7,8,9]

, где я ожидал бы [5,6,7,8,9]

Однако определение фильтра карри следующим образом работает:

const curriedFilter = (predicate) => (array) => array.filter(predicate);

Неужели я неправильно понимаю использование curryRight?

Ответы [ 2 ]

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

Ваш код не работает, потому что карта передает curriedFilter 3 аргумента - предикат, индекс и исходный массив. Вам нужно будет передать только предикат curriedFilter.

const { curryRight, filter, flow, ary } = _;

const curriedFilter = ary(curryRight(filter), 1);

const filterFromPredicates = (predicateList) => flow(...predicateList.map(curriedFilter)); // limit the number of params passed to curriedFilter

const fn = filterFromPredicates([x => x > 2, x => x < 6]); // don't override the filter you've imported

const result = fn([1,2,3,4,5,6,7,8,9]); // -> [3, 4, 5]

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

Другим вариантом будет ограничение количества параметров, которые curriedFilter принимает с помощью _.ary():

const { curryRight, filter, flow, ary } = _;

const curriedFilter = ary(curryRight(filter), 1);

const filterFromPredicates = (predicateList) => flow(...predicateList.map(curriedFilter)); // limit the number of params passed to curriedFilter

const fn = filterFromPredicates([x => x > 2, x => x < 6]); // don't override the filter you've imported

const result = fn([1,2,3,4,5,6,7,8,9]); // -> [3, 4, 5]

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

Вы можете использовать _.overEvery() для генерации предиката, который вы передадите фильтру карри:

const { flow, overEvery, curryRight, filter } = _;

const filterFromPredicates = flow(overEvery, curryRight(filter));

const fn = filterFromPredicates(x => x > 2, x => x < 6); // don't override the filter you've imported

const result = fn([1,2,3,4,5,6,7,8,9]); // -> [3, 4, 5]

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

Если вы используете lodash / fp, вам понадобится _.curryRight(), так как функции автоматически каррируются, а параметры - данные-итерацией-первым-последними:

const { flow, overEvery, filter } = _;

const filterFromPredicates = flow(overEvery, filter);

const fn = filterFromPredicates([x => x > 2, x => x < 6]); // don't override the filter you've imported

const result = fn([1,2,3,4,5,6,7,8,9]); // -> [3, 4, 5]

console.log(result);
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>
1 голос
/ 30 октября 2019

Как насчет этого:

function filterFromPredicates(predicates) {
 return (...args) => predicates
  .map(predfn=> predfn(...args))
  .every(a=>a)
}
[1,2,3,4,5,6,7,8,9].filter(filterFromPredicates([(x) => x > 2, (x) => x > 4]))

, если вы хотите, чтобы все выполнялось в одной и той же функции, то:

function filterFromPredicates(predicates) {
     return (someArray)=> someArray.filter((...args) => predicates
      .map(predfn=> predfn(...args))
      .every(a=>a))
    }

const filter = filterFromPredicates([(x) => x > 2, (x) => x > 4])
filter([1,2,3,4,5,6,7,8,9])

Это вернется, как вы хотели ^

...