首页 > 解决方案 > Ramda:如何通过柯里化、过滤和映射来最小化计算资源?

问题描述

我正在使用 Ramda 构建一个 React 应用程序。我还是函数式编程的新手(大约两个月)。

我有一个这样的联系人列表:

const contacts = [
  {
    id: 1,
    firstName: 'Sven',
    lastName: 'Hillstedt',
    city: 'Aachen',
    company: '',
    position: 'Student',
    group: 'friends',
    tendency: 'maintain'
  },
  {
    id: 2,
    firstName: 'David',
  // ...
];

给定一个字符串,我需要过滤这个(很长,10.000-100.000)列表。但我只需要考虑键firstName, lastName,city和. 有一个包含这些的数组:companyposition

const FIRST_NAME = 'firstName';
const LAST_NAME = 'lastName';
const CITY = 'city';
const COMPANY = 'company';
const POSITION = 'position';

export const stringFields = [FIRST_NAME, LAST_NAME, CITY, COMPANY, POSITION];

现在,我使用 Ramda 编写了以下函数,它接受一个string和一个联系人列表,映射联系人的键,选择相关的键并将它们小写,然后返回过滤后的联系人:

import { any, filter, includes, map, pick, pipe, toLower, values } from 'ramda';

const contactIncludesValue = value =>
  pipe(
    pick(stringFields),
    map(toLower),
    values,
    any(includes(value))
  );

const filterContactsByValue = value => filter(contactIncludesValue(value));

正如您所看到的,这段代码很混乱(甚至认为它比命令式执行要漂亮得多)。我咖喱value =>很多次,感觉不太理想。我也在质疑,这段代码是否只对联系人进行一次迭代,以及它是否有效。

您将如何过滤和映射(仅选择相关键 + lowerCase)大量联系人而不对其进行两次或更多次迭代?有没有办法避免我的柯里化并写出这个更清洁的东西?

标签: javascriptarraysfunctional-programmingcurryingramda.js

解决方案


这里有几件事需要回应。

  • 即使评论有点刻薄,@zerkms 也是对的。除非您知道代码实际上性能不佳,否则尝试性能优化几乎没有意义特别是如果它使代码更难编写或维护。

  • 你不会value =>多次咖喱。它只在前面进行了咖喱,并且每次过滤列表都会发生一次您的值的部分应用。

  • 您只迭代一次您的联系人。但在每一个内部都是any对您的字段列表的调用。如果找到匹配项,它会提前返回,因此计算调用次数并非易事,但它可能是字段数和联系人数O(m * n)在哪里。mn

这个版本的代码稍微更简洁。您可能会或可能不会发现它更具可读性:

const contactIncludesValue = value =>
  pipe(
    props(stringFields),
    map(toLower),
    any(includes(value))
  );

const filterContactsByValue = pipe(contactIncludesValue, filter);

请注意,这props比 更方便pick(...) -> values,并且中间的map(toLower)工作也一样好。


推荐阅读