joy08
joy08

Reputation: 9652

Grouping and adding array of objects to a complex object: Javascript

I have a complex object where some array of objects that needs to be added ( grouping based on field and adding)

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": "fiedl2","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 


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 directly add it to the "and" array of objects.

Help would be appreciated.

Upvotes: 0

Views: 86

Answers (1)

adiga
adiga

Reputation: 35222

  • concat the filter.and and obj array together.
  • reduce the resulting array.
  • Create an accumulator with each field as key.
  • If the key already exists and has a or property, add the current object to the or array.
  • If the key exists but doesn't have or property, create an array with existing object in the accumulator and current object being iterated.
  • If the key doesn't exist, add the key and set it to the current object.
  • Then use Object.values() on the resulting object to get the and array.

let 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"}];

const merged = obj.concat(filterObj.filter.and || []).reduce((r, o) => {
  if(r[o.field] && r[o.field].or) 
    r[o.field].or.push(o);
  else if(r[o.field])
    r[o.field] = { or: [r[o.field], o] }
  else
    r[o.field] = o;
 return r;
}, {})

const filter = { and: Object.values(merged) },
      { feature } = filterObj;

console.log({ feature, filter })
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 1

Related Questions