Skip to content
Advertisement

how to set object keys to common denominators?

I have an array of objects and want every object in the array to have the same keys.

var obj1 = {"type": "test", "info": "a lot", "value": 7};
var obj2 = {"value": 5};
var obj3 = {"context": "demo", "info": "very long", "value": 3};
var obj4 = {"info": "no way"};

var dataSet = [obj1,obj2,obj3,obj4];

My attempt is to create an array with all possible keys in the first step. Then loop through that keys array and update the objects if the key was not found.

keys.forEach(function(a,b){
  dataSet.forEach(function(c,d){    
    //key not found
    if(a in c === false)
    {
      //add key to object 
      dataSet[b][a] = false;
    }
  });
});

Howewer, it does not seem to work correctly. This is my output:

after logic:  [
  {
    "type": false,
    "info": "a lot",
    "value": 7
  },
  {
    "value": 5,
    "info": false
  },
  {
    "context": "demo",
    "info": "very long",
    "value": false
  },
  {
    "info": "no way",
    "context": false
  }
]

What am I missing there?

var obj1 = {"type": "test", "info": "a lot", "value": 7};
var obj2 = {"value": 5};
var obj3 = {"context": "demo", "info": "very long", "value": 3};
var obj4 = {"info": "no way"};

var dataSet = [obj1,obj2,obj3,obj4];
var keys    = [];

console.log("before logic: ", dataSet);

//Step 1: Fill keys array
dataSet.forEach(function(a,b){  
  Object.keys(a).forEach(function(c,d)
  {
    //add keys to array if not already exists
    if(!keys.includes(c))
    {
      keys.push(c);
    }
  });
});

//Step2: loop through keys array and add key to object if not existing
keys.forEach(function(a,b){
  dataSet.forEach(function(c,d){    
    //key not found
    if(a in c === false)
    {
      //add key to object 
      dataSet[b][a] = false;
    }
  });
});

console.log("after logic: ", dataSet);

EDIT:

It would be perfect if the keys are always sorted in the same order too.

Answer

You can just collect the keys in a Set using flatMap(), and then assign the missing ones using forEach():

const dataSet = [
  {"type": "test", "info": "a lot", "value": 7},
  {"value": 5},
  {"context": "demo", "info": "very long", "value": 3},
  {"info": "no way"}
];

const keys = new Set(dataSet.flatMap(Object.keys));

dataSet.forEach((v) => keys.forEach((k) => v[k] = k in v ? v[k] : false));

console.log(dataSet);

To address the additional request of having the keys in the same order, note that historically, JavaScript object properties were unordered, so relying on the order of object properties in JavaScript is almost never a good idea.

That being said, it’s hard to get a fixed order when modifying the existing objects, but doable if you create new objects:

const dataSet = [
  {"type": "test", "info": "a lot", "value": 7},
  {"value": 5},
  {"context": "demo", "info": "very long", "value": 3},
  {"info": "no way"}
];

const keys = [...new Set(dataSet.flatMap(Object.keys))];

const result = dataSet.map((v) => keys.reduce((a, k) => ({
  ...a,
  [k]: k in v ? v[k] : false
}), {}));

console.log(result);
Advertisement