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

Time:10-19

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>

  • Related