While joining two arrays, postfix non-unique values with (number) incrementally of joining array

I have two arrays:

  • Array 1 : [{name: "Darin", id: "123"}, {name: "Mads", id: "345"}, {name: "Kenneth", id: "543"}, {name: "June", id: "567"}, {name: "June (1)", id: "789"}]
  • Array 2 : [{name: "Darin", id: "910"}, {name: "June", id: "911"}, {name: "Simon", id: "912"}, {name: "Justin", id: "913"}]

The output that I want is as follows:

[{name: "Darin", id: "123"}, {name: "Mads", id: "345"}, {name: "Kenneth", id: "543"}, {name: "June", id: "567"}, {name: "June (1)", id: "789"}, {name: "Darin (1)", id: "910"}, {name: "June (2)", id: "911"}, {name: "Simon", id: "912"}, {name: "Justin", id: "913"}]

As you can see, I have the following rules:

  • Array 2 should be the only array in which I postfix (…num)
  • Eventual duplicates should be postfixed with (number) where number increments until the value becomes unique in the joined array

I’m unsure where to start in order to achieve the above. I can see this solved with a bunch of loops and a recusive function – But really, that’s inefficient.

I can see that Javascript ES6 offers some “newer” methods that could pose handy in this scenario – In particular map and set.

Consequently, my question seeks to understand how I can achieve the above, while paying attention to time complexity.

Answer

Using Array.map, and a counter object to keep track of the number of times each name already occurred:

var input1 = [{name: "Darin", id: "123"}, {name: "Mads", id: "345"}, {name: "Kenneth", id: "543"}, {name: "June", id: "567"}, {name: "June (1)", id: "789"}];

var input2 = [{name: "Darin", id: "910"}, {name: "June", id: "911"}, {name: "Simon", id: "912"}, {name: "Justin", id: "913"}];

var counter = {};
var combined = input1.concat(input2).map(function(e) {
  var strippedName = e.name.replace(/ ([0-9]+)/, '');
  counter[strippedName] = counter[strippedName] == undefined ? 0 : counter[strippedName] + 1;
  e.name = strippedName + (counter[strippedName] ? ' ('+counter[strippedName]+')' : '');
  return e;
});
console.log(combined);