Manipulating a complex object based on an input array

江枫思渺然 提交于 2020-01-05 07:09:33

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!