使用字符串 + 字符串数组过滤对象数组

Filtering an Array of Objects with a String + Array of Strings

我正在尝试了解如何更好地使用函数式编程来实现代码的整洁。理想情况下,我想为此使用 ramda.js,但我对任何其他功能库都持开放态度。

我有两个参数:

  1. emailSearchTerm 字符串
  2. [{ value: 'ACTIVE'}, { value: 'INACTIVE'}] 对象数组

我有一个数组,我希望通过上面的两个参数进行过滤:

[
  {
    email: '123@example.com',
    status: 'ACTIVE'
  },
  {
    email: '1234@whosebug.com',
    status: 'INACTIVE'
  },
]

如何使用利用两个输入的纯函数来有效地过滤一组对象?

编辑:很好的后续问题:

现在我使用搜索词进行部分过滤:

searchTerm ? userList.filter(user => user.email.toLowerCase()
    .indexOf(searchTerm.toLowerCase()) > -1) : userList

userList 表示对象数组,而我的 searchTerm 三元函数查找部分匹配项。我的目总结一下,标准是:

  1. 通过电子邮件输入部分匹配到 userList
  2. 中的电子邮件 属性
  3. 状态完全匹配
  4. 两个参数都需要满足

您可以使用 .filter 并检查 email 属性 是否包含具有 .includes() 函数的 emailSearchTerm 字符串,并使用 .some(哪个将测试数组中是否至少有一个元素通过提供的函数实现的测试。)用于通过 status 属性

检查和过滤

const emailSearchTerm = '123@example.com';
const arrayCheck = [{ value: 'ACTIVE'}, { value: 'INACTIVE'}];

const userList = [
  {
    email: '123@example.com',
    status: 'ACTIVE'
  },
  {
    email: '1234@whosebug.com',
    status: 'INACTIVE'
  },
]

const pureFunction = (string, arrayCheck, data) =>
   data.filter(item =>
      item.email.includes(string)
      && arrayCheck.some(obj => obj.value === item.status));

console.log(pureFunction(emailSearchTerm, arrayCheck, userList));

编辑

我的代码已更新,我将过滤器功能添加到纯函数中,因此您可以将其用作具有与现在相同数据类型的纯函数

这是一种使用普通方法的可能方法 JavaScript。

我利用柯里化和部分应用程序。检查匹配电子邮件的内容如何可以是任何 matcher。我提供了 partialMatch 但你可以实现任何函数来提供更复杂的匹配器。

const equals = x => y => x === y

const contains = xs => x => 
     xs.some (equals (x))
     
const partialMatch = x => y => y.toLowerCase().indexOf (x.toLowerCase()) > -1

// Note that turning that array of objects with  { value: '[STATUS]' }
// should be transformed to an array of string to make things simpler!
const anyStatus = contains (['ACTIVE', 'INACTIVE'])
const activeStatus = contains (['ACTIVE'])

const matchUser = containsStatus => emailMatcher => userList =>
      userList.filter (({ email, status }) =>
          emailMatcher (email)
          && containsStatus (status)
      )

const matchAnyUserStatus = matchUser (anyStatus)
const matchActiveUser = matchUser (activeStatus)

const emailHasAt = partialMatch ('@')
const emailHas123 = partialMatch ('123')

const userList = [{
    email: '123@example.com',
    status: 'ACTIVE'
  },
  {
    email: '1234@whosebug.com',
    status: 'INACTIVE'
  }
]

const output1 = matchAnyUserStatus (emailHasAt) (userList)
const output2 = matchAnyUserStatus (emailHas123) (userList)
const output3 = matchActiveUser (emailHas123) (userList)

console.log (output1)
console.log (output2)
console.log (output3)

这是一个使用 Ramda 的解决方案:

const {curry, contains, __, where, filter} = R; // Ramda

const search = curry(function (statuses, emailMatch, list) {
  const email = contains(emailMatch);
  const status = contains(__, statuses);
  return filter(where({email, status}), list);
});

const userList = [
  {email: 'john@whosebug.com', status: 'ACTIVE'},
  {email: 'david@gmail.com', status: 'ACTIVE'},
  {email: 'peter@gmail', status: 'INACTIVE'},
  {email: 'tom@whosebug.com', status: 'INACTIVE'}
];

const searchActiveUsers = search(['ACTIVE']);
const searchAllUsers = search(['ACTIVE', 'INACTIVE']);
const searchActiveSoUsers = searchActiveUsers('Whosebug');
const searchAllGmailUsers = searchAllUsers('gmail');

console.log(searchActiveSoUsers(userList)); // john
console.log(searchAllGmailUsers(userList)); // david & peter
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>


快速解释:

咖喱

接受一个函数,returns 一个函数,该函数保持 returning 一个函数,直到提供了所有参数。示例:

const sum = curry((a, b, c) => a + b + c);
sum(10)(20)(30); //=> 60
sum(10, 20)(30); //=> 60
sum(10, 20, 30); //=> 60

这允许您创建绑定特定参数的函数:

const searchActiveUsers = search(['ACTIVE']);
const searchActiveSoUsers = searchActiveUsers('Whosebug');
searchActiveSoUsers(userList); // john

包含

获取一个值和一个列表,如果在列表中找到值,则return为真:(在 Ramda 中,字符串和数组是列表。)

contains('whosebug.com', 'john@whosebug.com'); //=> true
contains('ACTIVE', ['ACTIVE', 'INACTIVE']); //=> true

__

这是柯里化函数的 "placeholder" 参数。它允许我们稍后指定参数:

const foundInJohn = contains(__, 'john@whosebug.com');
foundInJohn('Whosebug'); //=> true
foundInJohn('gmail'); //=> false

哪里

获取函数对象和另一个对象,如果第二个对象属性 return 应用于第一个对象中的相应函数时为真,则 return 为真:

const soUser = where({email: contains('Whosebug')});
soUser({email: 'john@whosebug.com'}); //=> true
soUser({email: 'david@gmail.com'}); //=> false

过滤器

这有点类似于 Array 原型上的本机过滤器方法。

const filterGmail = filter(contains('gmail'));
filterGmail(['david@gmail.com', 'john@whosebug.com']); //=> ['david@gmail.com']