javascript - 如何根据新计算的查询数据为数组项创建自定义过滤条件?
问题描述
我有一个由查询参数返回的过滤器对象
url = /all?channels=calls,text&calls=voicemail,missed
const query = {
channels: 'calls,texts',
calls: 'voicemail,missed',
};
然后我有一组来自套接字的对象。
const arr = [
{
id: 1,
channel: 'SMS',
sent: '2021-08-22T03:21:18.41650+0000',
sender: {
contactType: 'business',
},
recipients: [
{
contactType: 'corporate',
},
],
direction: 'INBOUND',
},
{
id: 2,
channel: 'VOICE',
sent: '2021-08-20T23:15:56.00000+0000',
sender: {
contactType: 'business',
},
recipients: [
{
contactType: 'corporate',
},
],
callDetails: {
answered: false,
voicemail: true,
},
direction: 'INBOUND',
},
{
id: 3,
channel: 'VOICE',
sent: '2021-08-20T23:15:56.00000+0000',
sender: {
contactType: 'business',
},
recipients: [
{
contactType: 'corporate',
},
],
callDetails: {
answered: true,
voicemail: false,
},
direction: 'INBOUND',
},
{
id: 4,
channel: 'VOICE',
sent: '2021-08-20T23:15:56.00000+0000',
sender: {
contactType: 'business',
},
recipients: [
{
contactType: 'corporate',
},
],
callDetails: {
answered: false,
voicemail: false,
},
direction: 'INBOUND',
},
];
我想过滤掉与过滤器匹配的对象,但query
obj 不够友好,无法仅映射arr
。
使用上面共享的查询 obj ,我应该返回对象id:1
andid:2
和id:4
from arr
,因为这些对象符合sms, voicemail, & missed
我假设我需要一个修改后的查询 obj,它必须为每个属性提供各种条件,即calls: voicemail === callDetails.voicemail === true
或calls: received === callDetails.answered === true
我已经看过很多关于如何过滤具有多个匹配条件的对象数组的示例,但是由于属性的 req 具有多个条件,所以我碰壁了。
谢谢您的帮助
解决方案
主要思想是提供一种罗塞塔石碑,它可以将query
特定语法与任何列表项的特定数据结构进行桥接/映射。因此,最终将编写一个映射,该映射将query
' 结构考虑在内,但确保每个必要的查询端点都有一个项目特定的过滤条件/功能。
查询函数应该filter
通过应用逻辑 OR 条件列表来简单地列出项目列表,从而some
用于返回布尔过滤器值。
剩下的就是实现一个辅助方法,该方法基于系统提供的对象,从上面介绍的配置/映射中收集...通过Object.entries
和Array.prototype.flatMap
以及通过String.prototype.split
和Array.prototype.map
...功能端点。因此这个助手可能被命名为.requirements
query
resolveQuery
const sampleList = [{
id: 1,
channel: 'SMS',
direction: 'INBOUND',
}, {
id: 2,
channel: 'VOICE',
callDetails: {
answered: false,
voicemail: true,
},
direction: 'INBOUND',
}, {
id: 3,
channel: 'VOICE',
callDetails: {
answered: true,
voicemail: false,
},
direction: 'INBOUND',
}, {
id: 4,
channel: 'VOICE',
callDetails: {
answered: false,
voicemail: false,
},
direction: 'INBOUND',
}];
// prepare a `requirements` map which ...
// - on one hand maps `query`-syntax to a list items's structure
// - and on the other hand does so by providing an item specific
// filter condition/function for each necessary query endpoint.
const requirements = {
channels: {
texts: item => item.channel === 'SMS',
},
calls: {
voicemail: item => item.channel === 'VOICE' && !!item.callDetails.voicemail,
missed: item => item.channel === 'VOICE' && !item.callDetails.answered,
},
}
// const query = {
// channels: 'calls,texts',
// calls: 'voicemail,missed',
// };
function resolveQuery(requirements, query) {
const reject = item => false;
// create/collect a list of filter condition/functions
// which later will be applied as logical OR via `some`.
return Object
.entries(query)
.flatMap(([ groupKey, groupValue ]) =>
// e.g groupKey => 'channels',
// groupValue => 'calls,texts'
groupValue
.split(',')
.map(requirementKey =>
// e.g requirementKey => 'calls'
// or requirementKey => 'texts'
requirements?.[groupKey]?.[requirementKey?.trim()] ?? reject
)
);
}
function queryFromItemList(itemList, requirements, query) {
const conditionList = resolveQuery(requirements, query);
console.log(
'conditionList ... [\n ',
conditionList.join(',\n '),
'\n]'
);
return itemList.filter(item =>
conditionList.some(condition => condition(item))
);
}
console.log(
queryFromItemList(sampleList, requirements, {
channels: 'calls,texts',
calls: 'voicemail,missed',
})
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
推荐阅读
- python - 如何从结构中打印字符串?
- javascript - 更正无效的路由命名
- histogram - 计算多个成对分布/直方图之间的总距离
- python - sklearn 指标分类_报告版本输出
- python - Scikit-learn 转换器管道产生的结果与单独运行不同
- c - 如何正确地将浮点数转换为 int
- javascript - 如何处理获取错误?
- python - Python:是否可以使用图像 URL 而不是图像文件将图像上传到 Firebase 存储?
- python - 烧瓶 send_file / send_from_directory 返回 200 状态码但不是文件
- typescript - 在 TSX 中仅转换 JSX 并维护 TS 的最佳方法