Home > Software design >  Taking an array of Objects and filtering each objects keys by an array of string
Taking an array of Objects and filtering each objects keys by an array of string

Time:08-07

I am pulling backend data to my application, but i want the user to be able to select which keys they want to see. So i have been trying to build a way for them to generate an array of strings and have that be compared to each object in the array and output the new array of objects with each key excluded.

Here is the Filter array:

const filterData = 
[
'TestOne',
'TestTwo',
]

Here is the array of objects:

const data = [
  {
    _id: "62ec2f1084c7f48175a9cb4a",
    Date: "2022-08-04T15:41:37.567Z",
    facilityId: "62e5a9fd45f2646fc7361fa3",
    userId: "62e16d390f4685e4fdb6a288",
    formData: {
      Date: "2022-08-04T15:41:37.567Z",
      TestOne: 60002,
      TestTwo: 19998,
      TestThree: 102,
      TestFour: "True"
    },
  },
  {
    _id: "62ec2f1c84c7f48175a9cb58",
    Date: "2022-08-04T15:41:52.932Z",
    facilityId: "62e5a9fd45f2646fc7361fa3",
    userId: "62e16d390f4685e4fdb6a288",
    formData: {
      Date: "2022-08-04T15:41:52.932Z",
      TestOne: 60003,
      TestTwo: 19997,
      TestThree: 103,
      TestFour: "True"
    },
  },
]

I want to build a function that takes the data.formData and filters out any keys that are not included in the filterData. I am having a hard time figuring out what exactly needs done to acheive this. If anyone could help id greatly appreciate it.

----EDIT---- Here is something of a process that i have thought of but it returns errors and cant really think of why.

  const formObject =
    datas.length > 0 &&
    datas.map((data, i) => {
      const filterData = ['TestOne', 'TestTwo']
      filterData.map((filter) => {
        delete data.formData[filter]
      })
    })

This function gives me errors of Uncaught TypeError: Cannot delete property 'TestThree' of #<Object>, ive tried making a new instance of datas but it doesnt work

CodePudding user response:

I would do it this way:

const result = data.map(x => {
    for (const [key, value] of Object.entries(x.formData)) {
        if (!filterData.includes(key)) {
            delete x.formData[key];
        }
    }
    return x;
})

Hope this helps

CodePudding user response:

The key highlights to this function are:

  • Before the first loop, the array is cloned then each object is skimmed over to find "formData". Since the actual keys are known, I'm going on the logical assumption that the object that has them is known as well -- hence the second parameter path.

    Object.keys(obj['formData']) = ["Date", "TestOne", "TestTwo", "TestThree", "TestFour"] :

    Figure I

    function filterData(array, path, ...keys) {
       let clone = structuredClone(array);
       for (let obj of clone) {
    
         Object.keys(obj[path]).flatMap(key =>
               //... obj[path] = [ {{["formData"]}}...
                 //... ["Date", "TestOne", "TestTwo", "TestThree", "TestFour"]
    
  • On the second loop, the keys form the first loop is checked vs. the third parameter ...keys, a rest parameter that consists of one or more keys to filter out. The if condition has been reversed with ! operator:

    Figure II

    if (![...keys].includes(key)) {
      return [];
    }
    return delete obj[path][key];
    

The TypeError sounds like the object is frozen so by cloning the array you can freely work on the clone.

const data = [{
  _id: "62ec2f1084c7f48175a9cb4a",
  Date: "2022-08-04T15:41:37.567Z",
  facilityId: "62e5a9fd45f2646fc7361fa3",
  userId: "62e16d390f4685e4fdb6a288",
  formData: {
    Date: "2022-08-04T15:41:37.567Z",
    TestOne: 60002,
    TestTwo: 19998,
    TestThree: 102,
    TestFour: "True"
  }
}, {
  _id: "62ec2f1c84c7f48175a9cb58",
  Date: "2022-08-04T15:41:52.932Z",
  facilityId: "62e5a9fd45f2646fc7361fa3",
  userId: "62e16d390f4685e4fdb6a288",
  formData: {
    Date: "2022-08-04T15:41:52.932Z",
    TestOne: 60003,
    TestTwo: 19997,
    TestThree: 103,
    TestFour: "True"
  }
}];


/**
 * Find any given number of keys and remove them
 * @param {array<object>} array - An array of objects
 * @param {string} path - Name of the key if the target object is one
 *        level down. (todo: recusive algorithm to dig deeper)
 * @param {string/array<string>} keys - List of keys to filter out
 * @return {array<object>} The array sans filered keys
 */
function filterData(array, path, ...keys) {
  let clone = structuredClone(array);
  for (let obj of clone) {
    Object.keys(obj[path]).flatMap(key => {
      if (![...keys].includes(key)) {
        return [];
      }
      return delete obj[path][key];
    });
  }
  return clone;
}

let x = filterData(data, "formData", "Date", "TestFour");

console.log(x);

  • Related