说我有这两个过滤器:
const getNamesStartingWith = (letter) => persons => {
return persons.filter(person => person.name.startsWith(letter);
}
const getPersonsStartingWithZipCode = (zipCode) => persons => {
return persons.filter(person => person.address.zipCode.startsWith(zipCode);
}
我想制作一个通用管道过滤器。
const pipeFilter = (funcArr, args) => arr => {
...
}
funcArr
是要运行的函数的数组。 args
是一个双精度数组,其中索引是函数的参数。
因此,在我的示例函数中,它将是:
const pipeFilter = ([getNamesStartingWith, getPersonsStartingWithZipCode], [['J'], [4]]) => persons => {..}
getNamesStartingWith
的参数为J
。 getPersonsStartingWithZipCode
的参数为4
如果我要“手动”操作,我会选择类似的东西:
export const doPipeFiltering = (funcArr: any[], args: any[]) => (arr) => {
return funcArr.reduce((acc, func, index) => {
let filterdArr;
if (index === 0) {
filterdArr = func(...args[index])(arr);
} else {
filterdArr = func(...args[index])(acc);
}
acc = filterdArr;
return acc;
}, []);
};
工作。但是我想在RamdaJs中做到这一点,所以我可以在那里使用所有简洁的函数。
我找不到如何在Ramda中为差异过滤器函数应用参数。有可能吗?
答案 0 :(得分:2)
使用Ramda函数,您绝对可以使它更干净。这是一种方法:
const doPipeFiltering = curry ( (funcArr, args, arr) =>
reduce ( (acc, func) => func (acc), arr, zipWith (apply, funcArr, args) ))
const getNamesStartingWith = (letter) => (persons) => {
return persons.filter(person => person.name.startsWith(letter))
}
const getPersonsStartingWithZipCode = (zipCode) => persons => {
return persons.filter(person => person.address.zipCode.startsWith(zipCode))
}
const people = [
{name: 'Amanda', address: {zipCode: '86753'}},
{name: 'Aaron', address: {zipCode: '09867'}},
{name: 'Amelia', address: {zipCode: '85309'}},
{name: 'Bob', address: {zipCode: '67530'}}
]
console .log (
doPipeFiltering (
[getNamesStartingWith, getPersonsStartingWithZipCode],
[['A'], ['8']],
people
)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script>const {curry, reduce, zipWith, apply} = R </script>
但是我建议这不是一个非常符合人体工程学的API。首先,如果过滤功能具有完全通用的接口,它可能还不错,但是现在您必须提供两个单独的数组参数,它们的值必须同步。对我来说,这是灾难的秘诀。
第二,为此我们需要创建的是过滤列表的函数。如果代码处理了过滤,我会发现它更加干净,我们只提供了一组简单的谓词。
对于我认为更清洁的API,这是另一种建议:
const runFilters = useWith (filter, [allPass, identity] )
// or one of these
// const runFilter = curry((filters, xs) => filter(allPass(filters), xs))
// const runFilters = curry ((filters, xs) => reduce ((a, f) => filter (f, a), xs, filters))
const nameStartsWith = (letter) => (person) => person.name.startsWith (letter)
const zipStartsWith = (digits) => (person) => person.address.zipCode.startsWith (digits)
const myFilter = runFilters ([nameStartsWith ('A'), zipStartsWith ('8')])
const people = [
{name: 'Amanda', address: {zipCode: '86753'}},
{name: 'Aaron', address: {zipCode: '09867'}},
{name: 'Amelia', address: {zipCode: '85309'}},
{name: 'Bob', address: {zipCode: '67530'}}
]
console .log (
myFilter (people)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script>const {useWith, filter, allPass, identity} = R </script>
请注意,这里的main函数更简单,filter谓词更简单,并且调用更加明确。 nameStartsWith ('A')
和zipStartsWith ('8')