我试图了解如何更好地使用函数式编程来实现代码的整洁。理想情况下,我想为此使用ramda.js
,但是我可以使用任何其他功能库。
我有两个参数:
emailSearchTerm
字符串[{ value: 'ACTIVE'}, { value: 'INACTIVE'}]
对象数组我有一个数组,希望通过上面的两个参数进行过滤:
[
{
email: '123@example.com',
status: 'ACTIVE'
},
{
email: '1234@stackoverflow.com',
status: 'INACTIVE'
},
]
如何使用一个纯函数来利用两个输入有效地过滤对象数组?
编辑:重要的后续问题:
目前,我已使用搜索词进行部分过滤:
searchTerm ? userList.filter(user => user.email.toLowerCase()
.indexOf(searchTerm.toLowerCase()) > -1) : userList
userList表示对象的数组,而我的searchTerm三元函数查找部分匹配项。我的目标是扩展此功能,使其具有更多状态”,我希望以一种易于理解的简洁,功能风格进行操作-这超出了我当前的技能水平。总而言之,标准是:
答案 0 :(得分:1)
您可以使用.filter
并使用email
函数检查emailSearchTerm
属性是否包含.includes()
字符串,并使用.some
(这将测试是否至少有一个数组中的元素通过了由提供的函数实现的测试。)用于通过status
属性进行检查和过滤
const emailSearchTerm = '123@example.com';
const arrayCheck = [{ value: 'ACTIVE'}, { value: 'INACTIVE'}];
const userList = [
{
email: '123@example.com',
status: 'ACTIVE'
},
{
email: '1234@stackoverflow.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));
编辑
我的代码已更新,我将过滤器功能添加到纯函数中,因此您可以将其用作具有与现在相同数据类型的纯函数
答案 1 :(得分:1)
这是使用原始JavaScript的一种可行方法。
我利用了currying和部分应用程序。检查匹配的电子邮件如何成为任何 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@stackoverflow.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)
答案 2 :(得分:1)
这是使用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@stackoverflow.com', status: 'ACTIVE'},
{email: 'david@gmail.com', status: 'ACTIVE'},
{email: 'peter@gmail', status: 'INACTIVE'},
{email: 'tom@stackoverflow.com', status: 'INACTIVE'}
];
const searchActiveUsers = search(['ACTIVE']);
const searchAllUsers = search(['ACTIVE', 'INACTIVE']);
const searchActiveSoUsers = searchActiveUsers('stackoverflow');
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>
快速说明:
咖喱
接收一个函数并返回一个函数,该函数将一直返回一个函数,直到提供了所有参数为止。示例:
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('stackoverflow');
searchActiveSoUsers(userList); // john
包含
获取一个值和一个列表,如果在列表中找到值,则返回true :(在Ramda中,字符串和数组是列表。)
contains('stackoverflow.com', 'john@stackoverflow.com'); //=> true
contains('ACTIVE', ['ACTIVE', 'INACTIVE']); //=> true
__
这是咖喱函数的“占位符”参数。它允许我们稍后指定参数:
const foundInJohn = contains(__, 'john@stackoverflow.com');
foundInJohn('stackoverflow'); //=> true
foundInJohn('gmail'); //=> false
位置
获取一个函数对象和另一个对象,如果将第二个对象属性应用于第一个对象中的相应函数,则返回true:
const soUser = where({email: contains('stackoverflow')});
soUser({email: 'john@stackoverflow.com'}); //=> true
soUser({email: 'david@gmail.com'}); //=> false
过滤器
这有点类似于Array原型上的本机过滤器方法。
const filterGmail = filter(contains('gmail'));
filterGmail(['david@gmail.com', 'john@stackoverflow.com']); //=> ['david@gmail.com']