ramda.js - 在 RamdaJS 中使用带参数的管道过滤器函数
问题描述
假设我有这两个过滤器:
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 中为不同的过滤器函数应用参数。可能吗?
解决方案
使用 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 函数更简单,过滤谓词更简单,调用更明确。特别改进的是nameStartsWith ('A')
和zipStartsWith ('8')
推荐阅读
- python - 陷波滤波器的脉冲响应
- c# - 如何知道调用者类 C#
- json - 从 JSON Golang 读取 PGP 密钥时出现 EOF 错误
- javascript - 如何在不丢失javascript功能的情况下用新的html替换元素内容?
- angular - 如何在Angular中选择全部和取消选择复选框?
- haskell - 无法将预期类型 'Char -> [Char] -> t' 与实际类型 'Char' 匹配
- ios - VimeoUpload - 未使用 KVO 方法接收上传进度更新
- html - Firebase Web应用程序中每一行的删除按钮
- mysql - 用于按属性过滤的 MySQL 查询
- python - 如果列表中的值重复,则应该在 python 中删除值?