Reputation: 4912
I am trying to write a functional solution to this problem. I already have a solution which uses a loop and mutation without recursion (I know what I have attempted below involves mutation, and I am trying to avoid this).
Please see the expected output in the comments below. I should emphasize that elements are not necessarily unique, and the sorting does not matter.
const getNamesWhichFillHoles = (namesArrayWithHoles, namesArrayFilled, fillers = []) => {
const holey = [...namesArrayWithHoles].filter(Boolean);
const filled = [...namesArrayFilled].filter(Boolean);
const fillerIndexInFilled = filled.findIndex(name => !holey.includes(name));
if (fillerIndexInFilled === -1) return fillers;
const filler = filled[fillerIndexInFilled];
const fillerIndexInHoley = holey.findIndex(name => name == filler);
fillers.push(filler);
filled[fillerIndexInFilled] = null;
holey[fillerIndexInHoley] = null;
return getNamesWhichFillHoles(holey, filled, fillers);
}
const namesArrayWithHoles = ['Bob', null, null, 'Sue', null];
const namesArrayFilled = ['Jim', 'Bob', 'Bob', 'Sam', 'Sue',];
const fillerNames = getNamesWhichFillHoles(namesArrayWithHoles, namesArrayFilled);
console.log(fillerNames); // [ 'Jim', 'Sam' ]
// should be: [ 'Jim', 'Sam', 'Bob' ]
Upvotes: 1
Views: 90
Reputation: 4912
I arrived at this solution. It does assume there are no null
values because that was just a distraction.
const getMissingValues = (partial, complete) => {
const equals = a => b => b == a;
const push = (arr, val, count) => count ? push([...arr, val], val, count - 1) : [...arr];
return [...new Set(complete)].reduce((missing, val) => {
const { length: a } = partial.filter(equals(val));
const { length: b } = complete.filter(equals(val));
const diff = (b - a);
return push(missing, val, diff);
}, []);
}
const partial = ['Bob', 'Sue'];
const complete = ['Jim', 'Bob', 'Bob', 'Bob', 'Sue', 'Sue', 'Sam'];
const missing = getMissingValues(partial, complete);
console.log(missing); // [ 'Jim', 'Bob', 'Bob', 'Sue', 'Sam' ]
Upvotes: 0
Reputation: 2312
You can do like the following:
const namesArrayWithHoles = ['Bob', null, null, 'Sue', null];
const namesArrayFilled = ['Jim', 'Bob', 'Bob', 'Sam', 'Sue'];
const result = namesArrayFilled.reduce(
(acc, elem) => {
const index = acc[0].indexOf(elem);
if (index != -1) {
return [acc[0].slice(0, index).concat(acc[0].slice(index + 1)), acc[1]];
}
return [acc[0], acc[1].concat(elem)];
},
[namesArrayWithHoles, []]
)[1];
console.log(result);
Upvotes: 1