我正在使用Ramda作为我的函数式编程助手库来构建React应用程序。
我正在努力建立自己的whereAny
。 Ramda暴露了where
,它检查它给出的每个道具是否满足相应的谓词。
我想构建一个接受键数组,对象和搜索项的函数,如果任何键(值是字符串)包含搜索项,它应该返回true
。如果不是,它应该返回false
。
这是我目前的解决方法:
export const whereAny = keys => obj => searchTerm =>
R.any(
R.pipe(
R.toLower,
R.includes(R.toLower(searchTerm))
),
R.values(R.pick(keys, obj))
);
export const contactNameIncludesSearchValue = whereAny(['firstName', 'lastName']);
正如您所看到的,我用它来查看某个联系人的某些值是否包含搜索词(IRL我使用的不仅仅是firstName
和lastName
)。
我的问题是你如何建立这样的whereAny
功能?我查看了Ramda cookbook和谷歌,找不到whereAny
的食谱。
我的解决方法的问题(除了它可能不是最佳的事实)是你不能像where
那样指定不同的功能。理想情况下,我的api看起来像这样:
const pred = searchValue => R.whereAny({
a: R.includes(searchValue),
b: R.equals(searchValue),
x: R.gt(R.__, 3),
y: R.lt(R.__, 3)
});
这就是我要做的事情:
const fromPair = R.apply(R.objOf);
const whereFromPair = R.compose(R.where, fromPair);
const whereAny = R.compose(R.anyPass, R.map(whereFromPair), R.toPairs);
只是tested it,它的工作原理。
我认为你应该使用Ramda的curry
来理解你的功能。
为什么?
使用这种形式的currying,你必须以这种方式调用它,只有这样:
const abc = a => b => c => a + b + c;
abc(1)(2)(3); // 6
而使用此表单您更灵活:
const abc = curry((a, b, c) => a + b + c);
abc(1, 2, 3); // 6
abc(1, 2)(3); // 6
abc(1)(2)(3); // 6
另请注意,Ramda函数倾向于接受它操作的数据作为最后一个参数:
Ramda功能自动curry。这使您可以通过不提供最终参数轻松地从旧功能构建新功能。
Ramda功能的参数被安排为便于卷曲。要操作的数据通常最后提供。
最后两点一起使得将函数构建为更简单函数的序列变得非常容易,每个函数都转换数据并将其传递给下一个。 Ramda旨在支持这种编码风格。
我想我们仍然可以使用这种方法来解决你的问题:
const whereAny = curry((keys, search, obj) =>
compose(includes(search), props(keys))
(obj));
const whereNameIsFoo = whereAny(['firstName', 'lastName'], 'foo');
console.log(whereNameIsFoo({firstName: 'john', lastName: 'foo'}));
console.log(whereNameIsFoo({firstName: 'bar', lastName: 'baz'}));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
<script>const {curry, compose, flip, includes, props} = R;</script>
我可能会使用Aadit M Shah的答案,但你也可以在implementation of where
上建模
const whereAny = R.curry((spec, testObj) => {
for (let [key, fn] of Object.entries(spec)) {
if (fn(testObj[key])) {return true}
}
return false
})
const pred = searchValue => whereAny({
a: R.includes(searchValue),
b: R.equals(searchValue),
x: R.gt(R.__, 3),
y: R.lt(R.__, 3)
});
console.log(pred("hello")({ a: [], b: "hola", x: 3, y: 2 }));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>