javascript - 使用Ramda(或其他功能库)使用indexOf过滤大数组对象?

标签 javascript arrays filter functional-programming ramda.js

我喜欢 Ramda,但有时我会在看似简单的事情上犯错误。 我所拥有的是我需要研究的地点和单词的列表(它们的indexOf必须等于0)以生成搜索建议列表,因此例如,给出下面的列表,我想向用户建议当他们在搜索框中输入“aber”时,会显示所有 3 个区域(按名称),但如果输入“nor”,则只会显示阿伯丁北。

[
  {
    name: "Aberavon",
    words: [ "aberavon" ]
  },
  {
    name: "Aberconwy",
    words: [ "aberconwy" ]
  },
  {
    name: "Aberdeen North",
    words: [ "aberdeen", "north" ]
  },
]

我设法让“正确”的东西运行,通过控制台日志获取结果,但是我似乎没有得到过滤的项目。我的代码如下所示,控制台日志将正确显示单词的迭代以及与术语开头匹配的索引,但我从未将对象从过滤器中取出。我试图让它变得更实用,甚至更不起作用,但到目前为止还没有结果!这是我的代码:

var matches = R.filter ( function ( x ) { R.map ( function ( word ) {
        console.log ( word );
        console.log ( word.indexOf ( term ) === 0 );
        R.equals ( word.indexOf ( term ), 0 )
    } ) ( x.words ) } ) ( json );

最佳答案

不是 Ramda 专家,但我也许可以提供帮助。

传递给 R.filter 的函数(第一个参数)应该采用一个 object 并返回一个 bool

关键是以可读且可重用的方式创建此方法。最终,你会得到类似这样的结果:

  • 从对象 {} 转换为字符串数组 [string]
  • 从字符串数组[string]转换为 bool 值bool

第 1 步:检查单词是否与术语匹配

目前,您已经定义了一个基本上是您的“开头为”测试的函数:

R.equals ( word.indexOf ( term ), 0 )

此函数需要两个字符串才能工作:wordterm(从技术上讲,它们可以是任何实现 indexOf 的东西,但让我们坚持看这个例子)

我首先测试这个方法并给它一个名称,这样你就知道这部分已经“完成”并且可以工作了。

const startsWith = term => word => word.indexOf(term) === 0;

(稍后,您可以重写它以使用 Ramda API 并包含其他功能,例如区分大小写。您可能还想注释诸如 string -> string -> bool 之类的内容,但是再说一遍,我不知道 Ramda 方式)

第 2 步:检查某个字符串是否与术语匹配

现在您可以检查字符串是否与某个术语匹配,您需要查明字符串数组中的至少一个字符串是否与某个术语匹配。

用纯 JavaScript 表示:

const anyStartsWith = term => arr => arr.some(startsWith(term));

我认为 Ramda 的等价物是 R.any :

const anyStartsWith = term => R.any(startsWith(term));

再次测试此方法,看看它的性能是否符合您的预期。

第 3 步:检查地点是否与术语匹配

这是最复杂的一步。我们需要从具有 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 方法:)

关于javascript - 使用Ramda(或其他功能库)使用indexOf过滤大数组对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43977439/

相关文章:

javascript - 基于 Electron-vue 的 Electron 应用中 Vuex 突变的奇怪行为

javascript - 访问多个参数

java - 多个列表或列表和 getSublist() (Java)

javascript - 使用 .NET MVC 中的 Response.Filter 将所有 JavaScript 保留在页面底部

Javascript 奇怪的 If 语句不起作用

javascript - 在 DOM 中找不到 RequireJs 对象(用于 UI 访问)

javascript - 没有域名可以创建cookie吗?

java - 比较数组并创建新数组 Android SDK

c - 关于使用数组乘以 C 中的多项式

date - 奇怪的Logstash日期解析错误