使用字符串 + 字符串数组过滤对象数组
Filtering an Array of Objects with a String + Array of Strings
我正在尝试了解如何更好地使用函数式编程来实现代码的整洁。理想情况下,我想为此使用 ramda.js
,但我对任何其他功能库都持开放态度。
我有两个参数:
emailSearchTerm
字符串
[{ 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 三元函数查找部分匹配项。我的目总结一下,标准是:
- 通过电子邮件输入部分匹配到 userList
中的电子邮件 属性
- 状态完全匹配
- 两个参数都需要满足
您可以使用 .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']
我正在尝试了解如何更好地使用函数式编程来实现代码的整洁。理想情况下,我想为此使用 ramda.js
,但我对任何其他功能库都持开放态度。
我有两个参数:
emailSearchTerm
字符串[{ 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 三元函数查找部分匹配项。我的目总结一下,标准是:
- 通过电子邮件输入部分匹配到 userList 中的电子邮件 属性
- 状态完全匹配
- 两个参数都需要满足
您可以使用 .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']