问题
I have an complex object and based on an input array I need to modify properties inside of this complex object. Illustration is shown below. I need to group them based on field values and then add them to the "or" array of objects(if field value is same). If not same,directly add it to the "and" array of objects. Need to read each field from the input array,and check if this is present inside "filter" of "filterObj" and if present add it to "and" else add it to the "or"
The format of both is shown below
//This is the source object where I need to add the below "arr" based on grouping
let filterObj = {
"feature": "test",
"filter": {
"and": [
{ "field": "field1","value": "1"}
]
}
};
//This array needs to be added to above object by grouping based on field
let obj = [
{"field" : "field1","value": "2"},
{"field" : "field2","value": "3"},
{"field" : "field2","value": "4"},
{"field" : "field3","value" : "5"}
]
I want the output to be of following format:
var result = {
"feature": "test",
"filter": {
"and": [
{
"or" : [
{"field": "field1","value": "1"},
{"field": "field1", "value": "2"}
]
},
{
"or" : [
{"field": "field2","value": "3"},
{"field": "field2","value": "4"},
]
},
{ "field": "field3", "value": "5"}
]
}
}
// The method that I have tried
filterObj.filter.and.or(...obj) ;// Does not work
回答1:
You could collect all same fields by a grouping and assign the values from grouping to and
property.
var filterObj = { feature: "test", filter: { and: [{ field: "field1", value: "1" }] } },
obj = [{ field: "field1", value: "2" }, { field: "field2", value: "3" }, { field: "field2", value: "4" }, { field: "field3", value: "5" }],
groups = obj.reduce(
(r, o) => {
if (r[o.field]) {
if (!('or' in r[o.field])) r[o.field] = { or: [r[o.field]] };
r[o.field].or.push(o);
} else {
r[o.field] = o;
}
return r;
},
(filterObj.filter.and || []).reduce((r, o) => {
r['or' in o ? o.or[0].field : o.field] = o;
return r;
}, {}));
filterObj.filter.and = Object.values(groups);
console.log(filterObj);
.as-console-wrapper { max-height: 100% !important; top: 0; }
回答2:
//This is the source object where I need to add the below "arr" based on grouping
let filterObj = {
"feature": "test",
"filter": {
"and": [
{ "field": "field1", "value": "1" }
]
}
};
//This array needs to be added to above object by grouping based on field
let obj = [
{ "field": "field1", "value": "2" },
{ "field": "field2", "value": "3" },
{ "field": "field2", "value": "4" },
{ "field": "field3", "value": "5" }
]
//obj = [{ "field": "field1", "value": "2" }]
let all_filters = [];
if (filterObj.filter.and && filterObj.filter.and.hasOwnProperty('or')) {
all_filters = [...filterObj.filter.and.or];
} else if (filterObj.filter.and) {
all_filters = [...filterObj.filter.and];
}
const all_objs = [...obj, ...all_filters];
// const all_objs = [...obj, ...filterObj.filter.and];
const uniqKeys = all_objs.reduce((acc, curr) => [...new Set([...acc, curr.field])], []);
const updateItems = uniqKeys.map(obj => {
const filter_items = all_objs.filter(item => item.field === obj);
let resultObj = {};
if (filter_items && filter_items.length > 1) {
resultObj.or = [...filter_items];
} else if (filter_items && filter_items.length == 1) {
resultObj = { ...filter_items[0] };
}
return resultObj;
})
var result = {...filterObj, filter: { and: [...updateItems] }};
console.log(result);
Please not that your input has "fiedl2" and "field2" (two different). I updated to same field name in the data here
来源:https://stackoverflow.com/questions/59458586/manipulating-a-complex-object-based-on-an-input-array