Reputation: 3579
I am having an nested array of objects like the below structure. I would like to loop into each object and check whether the particular field matches with a condition or not.If it matches then update that particular object.
Structure
{
"condition": "and",
"rules": [
{
"condition": "and",
"rules": [
{
"field": "deviceName",
"operator": "=",
"value": "device01"
},
{
"field": "temperature",
"operator": ">",
"value": 30
},
{
"field": "mail",
"operator": "to",
"value": "[email protected]"
}
]
},
{
"condition": "and",
"rules": [
{
"field": "deviceName",
"operator": "=",
"value": "device02"
},
{
"field": "voltage",
"operator": "=",
"value": 200
},
{
"field": "log",
"operator": "to",
"value": "[email protected]"
},
{
"condition": "and",
"rules": [
{
"field": "deviceName",
"operator": "=",
"value": "device04"
},
{
"field": "voltage",
"operator": "=",
"value": 200
},
{
"field": "mail",
"operator": "to",
"value": "[email protected]"
}
]
}
]
}
]
}
In the above structure i am checking each rules[] and check whether the field has the value email or log .If it matches then i am setting the type as action else condition.
I have tried map to do it but it works only at the first level. suppose if the object has nested array i couldn't able to filter it.
const queryDetail = this.query.rules.map((query: any) => {
const temp: any = {
condition: {
...query
}
};
if (query.field === 'mail' || query.field === 'log') {
temp.type = 'action';
} else {
temp.type = 'condition';
}
return temp;
});
const updatedQuery = {
condition: this.query.condition,
rules: queryDetail
};
Upvotes: 1
Views: 1398
Reputation: 28969
You do not need Lodash for this. You can take a recursive approach.
First off, rules are divided to "simple" and "complex"
field
, operator
, and value
fields.rules
property.With this in mind, apply the following logic to each rule:
'email'
or 'log'
, then set the type
of the current complex rule to 'action'
. Otherwise set it to 'condition'
. This will work even if the sub-rules are complex, since they do not have the field
property and thus will be treated the same as if they were simple rules that didn't match the filter.const data = { "condition": "and", "rules": [{ "condition": "and", "rules": [{ "field": "deviceName", "operator": "=", "value": "device01" }, { "field": "temperature", "operator": ">", "value": 30 }, { "field": "mail", "operator": "to", "value": "[email protected]" } ] }, { "condition": "and", "rules": [{ "field": "deviceName", "operator": "=", "value": "device02" }, { "field": "voltage", "operator": "=", "value": 200 }, { "field": "log", "operator": "to", "value": "[email protected]" }, { "condition": "and", "rules": [{ "field": "deviceName", "operator": "=", "value": "device04" }, { "field": "voltage", "operator": "=", "value": 200 }, { "field": "mail", "operator": "to", "value": "[email protected]" } ] } ] } ] }
function convertRule(obj) {
//clone the rule
const result = {...obj};
const isComplexRule = "rules" in obj;
if (isComplexRule) {
//check sub-rules
const isActionRule = obj.rules.some(checkSimpleRule);
//set the appropriate action
if (isActionRule) {
result.type = 'action';
} else {
result.type = 'condition';
}
//re-run the same logic on each sub-rule recursively
result.rules = result.rules.map(convertRule)
}
//return the cloned object
return result;
}
function checkSimpleRule(rule) {
return rule.field === 'mail' || rule.field === 'log'
}
const queryDetail = convertRule(data)
console.log(queryDetail)
Upvotes: 1