webbydevy
webbydevy

Reputation: 1220

How to modify an array of objects containing keys of the same name?

given the following array of objects:

p =[
{
    "object1": "value",
},
{
    "object2": "value",
},
{
    "object1": "value",
},
{
    "object3": "value",
},
{
    "object4": "value",
},
{
    "object1": "value",
},
{
    "object3": "value",
}
];

How would I modify the keys objects with the same key?

So that I have a new array like such:

p =[
{
    "object1_1": "value",
},
{
    "object2": "value",
},
{
    "object1_2": "value",
},
{
    "object3_1": "value",
},
{
    "object4": "value",
},
{
    "object1_3": "value",
},
{
    "object3_2": "value",
}
];

I need to keep the structure of the array nearly identical --with just updates to the duplicate keys.

Upvotes: 4

Views: 187

Answers (2)

Mariano Desanze
Mariano Desanze

Reputation: 8153

You will have to iterate through the array twice, once to check which keys are repeated, and a second time to replace the values.

var p = [{
  "object1": "value",
}, {
  "object2": "value",
}, {
  "object1": "value",
}, {
  "object3": "value",
}, {
  "object4": "value",
}, {
  "object1": "value",
}, {
  "object3": "value",
}];

var timesByKeys = {};
var numberByKeys = {};

function workOnEachKey(fn) {
  for (var i = 0; i < p.length; i++) {
    var o = p[i];
    var key = Object.keys(o)[0];
    var timesForKey = timesByKeys[key];
    fn(o, key, timesForKey);
  }
}

workOnEachKey(function(o, key, timesForKey) {
  timesByKeys[key] = timesForKey ? timesForKey + 1 : 1;
  numberByKeys[key] = 0;
});

workOnEachKey(function(o, key, timesForKey) {
  if (timesForKey !== 1) {
    var n = numberByKeys[key] + 1;
    numberByKeys[key] = n;
    o[key + "_" + n] = o[key];
    delete o[key];
  }
});

console.log(p);

Run the code snippet and check the console to see the result.

Upvotes: 0

Jonah Williams
Jonah Williams

Reputation: 21421

You could count the number of times each key value appears by creating a new object to track the existence of each key.

var set = {};

var changedArray = existingArray.map(function(d){
    // since each object has one key
    var key = Object.keys(d)[0];

    // if the key doesn't exist, add it.  if it does, increment it
    set[key] = (set[key] || 0) + 1

    // create the name
    var name = key + '_' + set[key];
    // create a new object with the given key
    var obj = {};
    obj[name] = d[key]; 
    return obj
});

EDIT:

Of course some good points raised below, don't use the name set. also you could avoid the '_1' for the first element by adding an if statement like so

var name;
if (set[key] === 1 ) { 
   name = key;
} else {
   name = key + '_' + set[key];
}

As far as having a '_1' only on elements that repeat - you could always loop through again using the final counts.

Upvotes: 3

Related Questions