Reputation: 6723
I have 2 arrays that change once in a while. I want to compare them and get the additions & deletions between the first, source array and the second array.
Additions/deletions can occur at the middle of the array (not necessarily at the edges).
For example, from these arrays:
Array 1
Item A | Item B | Item C | Item D | Item E
Array 2
Item A | Item Z | Item C | Item D | Item E
I would like to get the following output: - Item B was removed - Item Z was added
What is the best way to deal with this issue?
Upvotes: 1
Views: 628
Reputation: 7235
This can be accomplished in linear time.
When we have unique arrays (simpler algorithm)
const getDifferenceUnique = (arrayA, arrayB) => {
const valuesByFrequencies = (accumulator, value) => ({
...accumulator,
[value]: true,
});
const dictionaryA = arrayA.reduce(valuesByFrequencies, {});
const dictionaryB = arrayB.reduce(valuesByFrequencies, {});
return {
// get only those values from the `arrayA` that AREN'T present in the
// `arrayB`. This will get us an array containing the REMOVED items only.
deletions: arrayA.filter((value) => !dictionaryB[value]),
// get only those values from the `arrayB` that AREN'T present in the
// `arrayA`. This will get us an array containing the ADDED items only.
additions: arrayB.filter((value) => !dictionaryA[value])
}
};
const { deletions, additions } = getDifferenceUnique(['1', '2'], ['2', '3']);
console.log('Deletions', deletions);
console.log('Additions', additions);
When we have non-unique arrays
const getDifference = (arrayA, arrayB) => {
const valuesByFrequencies = (accumulator, value) => ({
...accumulator,
[value]: accumulator[value] ? accumulator[value] + 1 : 1
});
const dictionaryA = arrayA.reduce(valuesByFrequencies, {});
const dictionaryB = arrayB.reduce(valuesByFrequencies, {});
const createMapValuesByFrequencies = (dictionary) => ([key, frequency]) => {
const difference = (dictionary[key] || 0) - frequency;
return difference < 0 ? [key, difference] : null;
}
const filterNulls = (value) => value;
const getValuesByFrequencies = (accumulator, [key, frequency]) => [
...accumulator,
...key.repeat(Math.abs(frequency)).split('')
];
return {
deletions: Object.entries(dictionaryA)
.map(createMapValuesByFrequencies(dictionaryB))
.filter(filterNulls)
.reduce(getValuesByFrequencies, []),
additions: Object.entries(dictionaryB)
.map(createMapValuesByFrequencies(dictionaryA))
.filter(filterNulls)
.reduce(getValuesByFrequencies, [])
};
};
const { deletions, additions } = getDifference(['1', '2', '2', '2', '2'], ['2', '3', '3']);
console.log('Deletions', deletions);
console.log('Additions', additions);
Upvotes: 0
Reputation: 1
If the elements have random positions, the only think you can do is traverse the array in order to get sure of what elements are add or removed or you can use the underscore lib it has a package for node, too
the function is:
_.difference(array, *others)
Regards
Upvotes: -1
Reputation: 1233
If the item type is string, then follow this
var getAddedorRemovedItem = function (sourceArray1, sourceArray2) {
var added = [], removed = [];
sourceArray1.forEach(function(item){
if (sourceArray2.indexOf(item) == -1) {
removed.push(item);
}
});
sourceArray2.forEach(function (item) {
if (sourceArray1.indexOf(item) == -1) {
added.push(item);
}
});
// here added array contain all new added item and removed contain all removed item;
// do acc. to whatever you want to get outpur
}
Upvotes: 6