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.
CodePudding user response:
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);
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
You could count the names by separating the strings.
const
array1 = ["Darin", "Mads", "Kenneth", "June", "June (1)"],
array2 = ["Darin", "June", "Simon", "Justin"],
counts = {},
result = [array1, array2].reduce((r, a) => {
a.forEach(v => {
const [, name, , count = 0] = v.match(/^(\w*)(\s\((\d )\))?$/);
if (name in counts && count === 0) counts[name];
else counts[name] = count;
r.push(counts[name] ? `${name} (${counts[name]})` : name);
});
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>