Home > Enterprise >  Transform Array of objects of objects into new array of objects in tabular form
Transform Array of objects of objects into new array of objects in tabular form

Time:11-24

Given the sample data, I need to transform whats given and return in tabular form. Here is the sample data. How can I get the output to be what it is below?

var revisions = {
data:[
    // row 1
    {
      cId: {
        value: "123456",
        oldValue: null
      },
      revisionDate:{
        value: "09/01/2021",
        oldValue: "09/21/2021"
      },
      revisionType:{
        value: "UPDATE",
        oldValue: "DELETE"
      },
      revisionNote:{
        value: "Some test note 0",
        oldValue: "Old revision note 0"
      },
      financeNo:{
        value: "FA1",
        oldValue: "FA2"
      }
    },
    // row 2
    {
      dccId: {
        value: "123457",
        oldValue: null
      },
      revisionDate:{
        value: "05/01/2021",
        oldValue: "09/28/2021"
      },
      revisionType:{
        value: "NEW",
        oldValue: "UPDATE"
      },
      revisionNote:{
        value: "Some test note 1",
        oldValue: "Old revision note 1"
      },
      financeNo:{
        value: "FA4",
        oldValue: "FA5"
      },
      maintNo:{
        value: "MN001",
        oldValue: "MN002"
      },
      isSpare:{
        value: 0,
        oldValue: 1
      }
    },
    // row 3 ...
  ]
}

The console output should be:

[
  {cId: "123456", revisionDateNew: "09/01/2021", revisionDateOld:"09/21/2021", revisionTypeNew: "UPDATE",revisionTypeOld: "DELETE", revisionNoteNew: "Some test note 0", revisionNoteOld: "Old revision note 0", financeNoNew: "FA1", financeNoOld: "FA2", maintNoNew: "",      maintNoOld: "",      isSpareNew: "",  isSpareOld: ""},
  {cId: "123457", revisionDateNew: "05/01/2021", revisionDateOld:"09/28/2021", revisionTypeNew: "NEW",   revisionTypeOld: "UPDATE", revisionNoteNew: "Some test note 1", revisionNoteOld: "Old revision note 1", financeNoNew: "FA4", financeNoOld: "FA5", maintNoNew: "MN001", maintNoOld: "MN002", isSpareNew: "0", isSpareOld: "1"}, 
  ...
]

So far this is what Ive done but Im stuck on how to not hard code the properties and Im also struggling to figure out the logic needed to assign a 'New' and 'Old' to the current properties and then give those the correct values.

function loopData(revisions: any) {
  var newData = revisions.data.map(item => ({
    cId: item.cId.value,
    revisionDateNew: item.revisionDate.value
  }))
  console.log(newData)
}

I think what I need is another loop maybe a forEach where I get the keys and then create a new array to push the new fields.

CodePudding user response:

A general function I've used a lot objectMap to map each field in an object to some other data:

/**
 * similar to Array.map but for the fields of an object.
 * the callback takes the value as first argument and key as second.
 * does not support passing object as 3rd argument or thisArg.
 */
export function objectMap<T, V>(obj: T, fn: (val: T[keyof T], key: keyof T) => V) {
    // this is one of the cases where the as Record followed by a loop initializing all the keys
    // the whole reason this function exists is to have this typesafe outside :)
    // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
    const newObj = {} as Record<keyof T, V>;
    for (const [key, val] of Object.entries(obj)) {
        newObj[key as keyof T] = fn(val, key as keyof T);
    }
    return newObj;
}

With this you can get the correct data structure with this playground

const newData = revisions.data.map(v=>objectMap(v, x=>x?.value))

Note that it doesn't preserve the types completely as we'd need this feature to type this properly in general, you will likely want an interface to denote the type of the output anyway so this probably isn't a problem for you.

  • Related