0

Updated object keys

    let conditionedObject = {
        "isNameRequired": true,
        "isCityRequired": false,
        "isPostRequired": true
    };
    
    let myTotalData = {
     data: {
        "givenName": 'myname',
        "street":"mystreet",
        "cityName": 'mycity',
        "postcode": 'mypost'
      }
    };

let resultData = {};

Both condionedObject and myTotalData comes from different source. I would like to know the best way to create a new object based on the condionedObject, example my condionedObject says I need only name and post so my resultData should return {"givenName":"myname","postcode":"mypost"}

conditionedObject.isNameRequired is for myTotalData.data.givenName, conditionedObject.isPostRequired is for myTotalData.data.postcode, conditionedObject.isCityRequired is for myTotalData.data.cityName, all this will say whether myTotalData key is required to be placed in the new object.

Thanks in advance for all the suggestions and helps

1
  • All, The data of objects conditionedObject and myTotalData comes from different sources I gave sample key names, consider removing "is" from key names are not an option. consider them as isNameRequired, isCityRequired, isPostRequired..etc Commented Nov 5, 2020 at 11:55

3 Answers 3

1

You can use Array.prototype.reduce():

In this case I recommend you to create a new object to store the relationship between properties:

  

  let conditionedObject = {
  "isNameRequired": true,
  "isCityRequired": false,
  "isPostRequired": true
};

let myTotalData = {
  data: {
    "givenName": 'myname',
    "street":"mystreet",
    "cityName": 'mycity',
    "postcode": 'mypost'
  }
};

const reference = {
  "isNameRequired": "givenName",
  "isCityRequired": "cityName",
  "isPostRequired": "postcode"
}

let resultData = {};

resultData =Object.entries(conditionedObject).reduce((obj, [key, value]) => {
   if(value && myTotalData.data[reference[key]]) {
     const prop = reference[key]; 
     obj[prop] = myTotalData.data[prop];
   }
   return obj;
}, {});

console.log(resultData);

Sign up to request clarification or add additional context in comments.

2 Comments

your entries.reduce way of identifying the object is really good but the problem is that I don't have similar object structure or key name. I have updated my question can you try providing a efficient solution @lissettdm
I think, you need a way to map the props, could be something like this {"isNameRequired": "givenName"}, otherwise it is difficult to identify which properties to map.
1

Here is my solution:

You need to change the keys in the object conditionedObject and remove the is- prefix so that they are the same as the keys in myTotalData. This way the check is easier later.

Then it's pretty straight-forward.

let conditionedObject: {[key: string]: boolean} = {
    "isName": true,
    "isCity": false,
    "isPost": true
};

type DataType = {[key: string]: string};
let myTotalData: DataType = {
    "name": 'myname',
    "city": 'mycity',
    "post": 'mypost'
};

let resultData: DataType = {};
for(const key in conditionedObject) {
    // Ensure that the key is really part of this object
    if(!conditionedObject.hasOwnProperty(key)) {
        continue;
    }
    
    if(!conditionedObject[key]) {
        continue;
    }
    
    const dataKey = key.startsWith("is")
        ? key.charAt(2).toLowerCase() + key.substring(3)
        : key;

    if(myTotalData.hasOwnProperty(dataKey)) {
        resultData[dataKey] = myTotalData[dataKey];
    }
}

console.log(resultData);

Output:

{
    name: "myname",
    post: "mypost"
}

4 Comments

I cannot have the same keys in both the objects as they both come from different source, is there any other efficient way with the sample objects that I have provided.
Sure. I've updated my answer to use the original conditionedObject.
not working in TS and got the below error for line if(!conditionedObject[key]) { Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ isName: boolean; isCity: boolean; isPost: boolean; }'. No index signature with a parameter of type 'string' was found on type '{ isName: boolean; isCity: boolean; isPost: boolean; }'
@sunilsmith That error can be resolved by specifying the types of the data objects, as {[key: string]: boolean} and {[key: string]: strnig}. Updated the answer with the changes, and it no longer has that error.
0

You can use something like that, if you can be sure that the conditionedObject keys are always equal your myTotalData keys, but capitalized and with "is" on the front:

let capitalize = str => str.charAt(0).toUpperCase() + str.slice(1)
let prependIs = str => "is" + str

let conditionedObject = {
  "isName": true,
  "isCity": false,
  "isPost": true
};

let myTotalData = {
  "name": 'myname',
  "city": 'mycity',
  "post": 'mypost'
};

let filterData = (data, conditionObj) => Object.fromEntries(Object.entries(data)
  .filter(([key, _]) => conditionObj[prependIs(capitalize(key))]))

// More verbose alternative for browsers which doesn't support `Object.fromEntries()`
let filterDataAlt = (data, conditionObj) => {
  let result = {}
  let filteredEntries = Object.entries(data)
    .filter(([key, _]) => conditionObj[prependIs(capitalize(key))])
  for (let [key, value] of filteredEntries) {
    result[key] = value
  }
  return result
}

console.log(filterData(myTotalData, conditionedObject))
console.log(filterDataAlt(myTotalData, conditionedObject))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.