不是 Ramda 专家,但我可能可以提供帮助。
您传递给R.filter 的函数(第一个参数)应该采用object 并返回bool。
关键是以可读和可重用的方式创建此方法。最终,您会得到如下结果:
- 从对象
{} 转到字符串数组[string]
- 从字符串数组
[string] 转换为布尔值bool
第 1 步:检查 word 是否与 term 匹配
目前,您已经定义了一个基本上是您的“开始于”测试的函数:
R.equals ( word.indexOf ( term ), 0 )
此函数需要两个字符串才能工作:word 和 term。 (从技术上讲,它们可以是实现 indexOf 的任何东西,但让我们继续举例)
我会首先测试这个方法并给它一个名字,所以你知道这部分已经“完成”并且可以工作了。
const startsWith = term => word => word.indexOf(term) === 0;
(稍后,您可以重写它以使用 Ramda API 并包含其他功能,例如区分大小写。您可能还想注释 string -> string -> bool 之类的东西,但同样,我不知道 Ramda 方式)
第 2 步:检查 some 字符串是否匹配 term
现在您可以检查字符串是否与某个词匹配,您需要确定字符串数组中的至少一个字符串是否与某个词匹配。
在纯javascript中:
const anyStartsWith = term => arr => arr.some(startsWith(term));
我认为 Ramda 等价物是 R.any:
const anyStartsWith = term => R.any(startsWith(term));
再一次,测试这个方法,看看它是否像你想要的那样运行。
第 3 步:检查 Place 是否与术语匹配
这是最复杂的一步。我们需要从带有words 属性的object 转到我们之前定义的过滤器方法可以处理的东西。
const placeMatchesTerm = term => place =>
anyStartsWith(term) (place.words);
第 4 步:过滤
现在,我们有一个函数,它接受一个术语并返回一个接受Place 的函数。这个,我们可以用来直接过滤我们的地点数组:
const myPlaces = [ /* ... */ ];
const filter = (term, arr) =>
arr.filter(placeMatchesTerm(term));
const aber = filter("aber", myPlaces);
const nor = filter("nor", myPlaces);
在一个工作示例中(没有 Ramda)
// string -> string -> bool
const startsWith = term => word => word.indexOf(term) === 0;
// string -> [string] -> bool
const anyStartsWith = term => arr => arr.some(startsWith(term));
// string -> {} -> bool
const placeMatchesTerm = term => place => anyStartsWith(term) (place.words);
// string -> [{}] -> bool
const filter = term => arr =>
arr.filter(placeMatchesTerm(term));
const aber = filter("aber")(getPlaces());
const nor = filter("nor")(getPlaces());
console.log("'Aber' matches", aber.map(p => p.name));
console.log("'Nor' matches", nor.map(p => p.name));
// Data
function getPlaces() {
return [{name:"Aberavon",words:["aberavon"]},{name:"Aberconwy",words:["aberconwy"]},{name:"Aberdeen North",words:["aberdeen","north"]}];
}
在 Ramda 中,它可能类似于 this,但同样,我不是专家。我会将 Ramda 标签添加到您的问题中,这使得很可能有人会出现向您展示 Ramda 方式:)