如何根据新计算的查询数据为数组项创建自定义过滤条件?
How does one create custom filter conditions for array items upon ever newly computed query-data?
我有一个由查询参数 return 编辑的过滤器对象
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
。
使用上面共享的查询对象,我应该 return 来自 arr
的对象 id:1
和 id:2
以及 id:4
,因为这些对象满足sms, voicemail, & missed
的标准
我假设我需要一个修改后的查询对象,它必须具有可用于每个 属性 的各种条件,即 calls: voicemail === callDetails.voicemail === true
或 calls: received === callDetails.answered === true
我看过很多关于如何使用多个匹配条件过滤对象数组的示例,但是由于 属性 的请求具有多个条件,我遇到了困难。
感谢帮助
主要思想是提供一种 rosetta stone,它 bridge/map query
具体任何列表项的特定数据结构的语法。因此,最终将编写一个映射,该映射考虑了 query
的结构,但确保为每个必要的查询端点提供一个特定于项目的过滤器 condition/function.
查询函数应该简单地 filter
the item list by applying a list of logical OR conditions, thus using some
返回布尔过滤器值。
剩下的就是实现一个辅助方法,它收集... 通过Object.entries
and Array.prototype.flatMap
as well as via String.prototype.split
and Array.prototype.map
...上面介绍的函数端点requirements
configuration/map,基于系统提供的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; }
我有一个由查询参数 return 编辑的过滤器对象
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
。
使用上面共享的查询对象,我应该 return 来自 arr
的对象 id:1
和 id:2
以及 id:4
,因为这些对象满足sms, voicemail, & missed
我假设我需要一个修改后的查询对象,它必须具有可用于每个 属性 的各种条件,即 calls: voicemail === callDetails.voicemail === true
或 calls: received === callDetails.answered === true
我看过很多关于如何使用多个匹配条件过滤对象数组的示例,但是由于 属性 的请求具有多个条件,我遇到了困难。
感谢帮助
主要思想是提供一种 rosetta stone,它 bridge/map query
具体任何列表项的特定数据结构的语法。因此,最终将编写一个映射,该映射考虑了 query
的结构,但确保为每个必要的查询端点提供一个特定于项目的过滤器 condition/function.
查询函数应该简单地 filter
the item list by applying a list of logical OR conditions, thus using some
返回布尔过滤器值。
剩下的就是实现一个辅助方法,它收集... 通过Object.entries
and Array.prototype.flatMap
as well as via String.prototype.split
and Array.prototype.map
...上面介绍的函数端点requirements
configuration/map,基于系统提供的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; }