Deepika Deepi
Deepika Deepi

Reputation: 127

Filter an Array of Objects from another Array of Objects with a different nesting structure

I have 2 arrays. I need to change the key-value pair of the Objects in originalArray based on the objects from compareArray

    let originalArray = [
  {
    reportCatalogId: 111,
    catalogRootId: 11,
    reports: [
      {
        reportId: 90001,
        reportCatalogId: 111,
        provisioning: true
      },
      {
        reportId: 90002,
        reportCatalogId: 111,
        provisioning: true
      },
      {
        reportId: 90003,
        reportCatalogId: 111,
        provisioning: true
      }
    ]
  },
  {
    reportCatalogId: 112,
    catalogRootId: 11,
    reports: [
      {
        reportId: 90004,
        reportCatalogId: 112,
        provisioning: true
      },
      {
        reportId: 90005,
        reportCatalogId: 112,
        provisioning: true
      },
      {
        reportId: 90006,
        reportCatalogId: 112,
        provisioning: true
      },
      {
        reportId: 90007,
        reportCatalogId: 112,
        provisioning: true
      }
    ]
  }
];
let compareArray = [
  {
    "reportId": 90001,
    "reportCatalogId": 111,
    "provisioning": true
  },
  {
    "reportId": 90006,
    "reportCatalogId": 112,
    "provisioning": true
  },
  {
    "reportId": 90007,
    "reportCatalogId": 112,
    "provisioning": true
  },
  {
    "reportId": 90003,
    "reportCatalogId": 111,
    "provisioning": true
  }
]

I need to check if the object from compareArray is present in originalArray based on the reportId. If it is not present, then the respective object's key provisioningvalue should be changed into false.

Desired Output :

    let output = [
  {
    reportCatalogId: 111,
    catalogRootId: 11,
    reports: [
      {
        reportId: 90001,
        reportCatalogId: 111,
        provisioning: true
      },
      {
        reportId: 90002,
        reportCatalogId: 111,
        provisioning: false
      },
      {
        reportId: 90003,
        reportCatalogId: 111,
        provisioning: true
      }
    ]
  },
  {
    reportCatalogId: 112,
    catalogRootId: 11,
    reports: [
      {
        reportId: 90004,
        reportCatalogId: 112,
        provisioning: false
      },
      {
        reportId: 90005,
        reportCatalogId: 112,
        provisioning: false
      },
      {
        reportId: 90006,
        reportCatalogId: 112,
        provisioning: true
      },
      {
        reportId: 90007,
        reportCatalogId: 112,
        provisioning: true
      }
    ]
  }
];

What I tried so far is that

const newArray = originalArray.map((catalog) => catalog.reports.map((report) => {
  if (report.reportId !== compArray.map(id => id.reportId)) {
    return {...report, provisioning : false}
  } 
}))

But I could not produce the desired output with my above code. Glad if someone could show me a pointer.

Upvotes: 0

Views: 65

Answers (3)

A1exandr Belan
A1exandr Belan

Reputation: 4780

Lodash if you don't mind.

const originalArray = [{"reportCatalogId":111,"catalogRootId":11,"reports":[{"reportId":90001,"reportCatalogId":111,"provisioning":true},{"reportId":90002,"reportCatalogId":111,"provisioning":true},{"reportId":90003,"reportCatalogId":111,"provisioning":true}]},{"reportCatalogId":112,"catalogRootId":11,"reports":[{"reportId":90004,"reportCatalogId":112,"provisioning":true},{"reportId":90005,"reportCatalogId":112,"provisioning":true},{"reportId":90006,"reportCatalogId":112,"provisioning":true},{"reportId":90007,"reportCatalogId":112,"provisioning":true}]}];

const compareArray = [{"reportId":90001,"reportCatalogId":111,"provisioning":true},{"reportId":90006,"reportCatalogId":112,"provisioning":true},{"reportId":90007,"reportCatalogId":112,"provisioning":true},{"reportId":90003,"reportCatalogId":111,"provisioning":true}];

const compareIds = compareArray.map(({ reportId }) => reportId);
const hasCompareId = (id) => compareIds.includes(id);

const result = _.cloneDeepWith(originalArray, (_, key, obj) => {
  if (key === 'provisioning') return hasCompareId(obj.reportId);
});

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0 }
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>

Upvotes: 1

Mulan
Mulan

Reputation: 135277

Don't write the data by hand. Write functions to create your catalog and report data -

const catalog = (reportCatalogId, catalogRootId = null, reports = []) =>
  ({ reportCatalogId, catalogRootId, reports })

const report = (reportId, reportCatalogId = null, provisioning = false) =>
  ({ reportId, reportCatalogId, provisioning })

And make functions like updateProvisions to work on the data -

function updateProvisioning(cat, prov) {
  return catalog(cat.reportCatalogId, cat.catalogRootId, cat.reports.map(r =>
    report(r.reportId, r.reportCatalogId, prov.has(r.reportId))
  ))
}

Notice how the underlying cat is not modified. Instead a new data is returned.

Finally, construct a Set of the report IDs from the compareArray -

let compareArray =
  [{"reportId": 90001,"reportCatalogId": 111,"provisioning": true},{"reportId": 90006,"reportCatalogId": 112,"provisioning": true},{"reportId": 90007,"reportCatalogId": 112,"provisioning": true},{"reportId": 90003,"reportCatalogId": 111,"provisioning": true}]

let hasProvisioning =
  new Set(compareArray.map(x => x.reportId))

Now you simply map our new updateProvisioning function over each category -

let newArray =
  originalArray.map(cat => updateProvisioning(cat, hasProvisioning))

Run the demo below to verify the result in your own browser -

const catalog = (reportCatalogId, catalogRootId = null, reports = []) =>
  ({ reportCatalogId, catalogRootId, reports })

const report = (reportId, reportCatalogId = null, provisioning = false) =>
  ({ reportId, reportCatalogId, provisioning })
  

let compareArray =
  [{"reportId": 90001,"reportCatalogId": 111,"provisioning": true},{"reportId": 90006,"reportCatalogId": 112,"provisioning": true},{"reportId": 90007,"reportCatalogId": 112,"provisioning": true},{"reportId": 90003,"reportCatalogId": 111,"provisioning": true}]

let hasProvisioning =
  new Set(compareArray.map(x => x.reportId))

let originalArray =
  [{reportCatalogId: 111,catalogRootId: 11,reports: [{reportId: 90001,reportCatalogId: 111,provisioning: true},{reportId: 90002,reportCatalogId: 111,provisioning: true},{reportId: 90003,reportCatalogId: 111,provisioning: true}]},{reportCatalogId: 112,catalogRootId: 11,reports: [{reportId: 90004,reportCatalogId: 112,provisioning: true},{reportId: 90005,reportCatalogId: 112,provisioning: true},{reportId: 90006,reportCatalogId: 112,provisioning: true},{reportId: 90007,reportCatalogId: 112,provisioning: true}]}]

function updateProvisioning(cat, hasProvisioning) {
  return catalog(cat.reportCatalogId, cat.catalogRootId, cat.reports.map(r =>
    report(r.reportId, r.reportCatalogId, hasProvisioning.has(r.reportId))
  ))
}

let newArray = originalArray.map(cat => updateProvisioning(cat, hasProvisioning))


console.log(newArray)
.as-console-wrapper { min-height: 100%; top: 0; }

[
  {
    "reportCatalogId": 111,
    "catalogRootId": 11,
    "reports": [
      {
        "reportId": 90001,
        "reportCatalogId": 111,
        "provisioning": true
      },
      {
        "reportId": 90002,
        "reportCatalogId": 111,
        "provisioning": false     // <-
      },
      {
        "reportId": 90003,
        "reportCatalogId": 111,
        "provisioning": true
      }
    ]
  },
  {
    "reportCatalogId": 112,
    "catalogRootId": 11,
    "reports": [
      {
        "reportId": 90004,
        "reportCatalogId": 112,
        "provisioning": false     // <-
      },
      {
        "reportId": 90005,
        "reportCatalogId": 112,
        "provisioning": false     // <-
      },
      {
        "reportId": 90006,
        "reportCatalogId": 112,
        "provisioning": true
      },
      {
        "reportId": 90007,
        "reportCatalogId": 112,
        "provisioning": true
      }
    ]
  }
]

Upvotes: 2

Dylan Dang
Dylan Dang

Reputation: 166

Try this

originalArray.map(({reports, ...catalog}) => ({
    ...catalog,
    reports: reports.map((report) => ({
        ...report,
        provisioning: compareArray.some(({ reportId }) => reportId === report.reportId),
    })),
}));

Upvotes: 2

Related Questions