拉姆达:在哪里?
Ramda: whereAny?
我正在使用 Ramda 作为我的函数式编程助手库来构建 React 应用程序。
我正在努力打造自己 whereAny
。 Ramda 暴露了 where
来检查 每个 属性是否满足相应的谓词。
我想构建一个接受键数组、对象和搜索词的函数,如果任何键(值是字符串)包含搜索词,它应该 return true
.如果不是,它应该 return 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 和 Google,但找不到 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
.
柯里化你的函数
为什么?
使用这种柯里化形式,您必须这样调用它,而且只能这样调用:
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 functions are automatically curried. This allows you to easily build up new functions from old ones simply by not supplying the final parameters.
The parameters to Ramda functions are arranged to make it convenient for currying. The data to be operated on is generally supplied last.
The last two points together make it very easy to build functions as sequences of simpler functions, each of which transforms the data and passes it along to the next. Ramda is designed to support this style of coding.
我认为我们仍然可以使用这种方法来解决您的问题:
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>
老问题,但 Ramda 最近发布了 whereAny
。
我正在使用 Ramda 作为我的函数式编程助手库来构建 React 应用程序。
我正在努力打造自己 whereAny
。 Ramda 暴露了 where
来检查 每个 属性是否满足相应的谓词。
我想构建一个接受键数组、对象和搜索词的函数,如果任何键(值是字符串)包含搜索词,它应该 return true
.如果不是,它应该 return 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 和 Google,但找不到 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
.
为什么?
使用这种柯里化形式,您必须这样调用它,而且只能这样调用:
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 functions are automatically curried. This allows you to easily build up new functions from old ones simply by not supplying the final parameters.
The parameters to Ramda functions are arranged to make it convenient for currying. The data to be operated on is generally supplied last.
The last two points together make it very easy to build functions as sequences of simpler functions, each of which transforms the data and passes it along to the next. Ramda is designed to support this style of coding.
我认为我们仍然可以使用这种方法来解决您的问题:
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>
老问题,但 Ramda 最近发布了 whereAny
。