EN
JavaScript - detect array items changes (added, updated, removed, unchanged)
10
points
In this short article, we would like to show how to detect changes in an array in JavaScript.
As changes, we understand to detect what item was added, updated, removed or unchanged.
Note: in the below example, it is necessary to indicate own functions that:
- gets array item key -
getKey(item)
in the code,- compares array items to see difference -
compareItems(a, b)
in the code.
Quick solution:
// ONLINE-RUNNER:browser;
function mapItems(items, getKey) {
var map = {};
for (var i = 0; i < items.length; ++i) {
var item = items[i];
var key = getKey(item);
if (key in items) {
throw new Error('Item key is duplicated (' + key + ').');
}
map[key] = item;
}
return map;
}
function detectChanges(prevItems, nextItems, getKey, compareItems) {
var mappedItems = mapItems(prevItems, getKey);
var detectedChanges = {
addedItems: [],
updatedItems: [],
removedItems: [],
unchangedItems: []
};
for (var i = 0; i < nextItems.length; ++i) {
var nextItem = nextItems[i];
var itemKey = getKey(nextItem);
if (itemKey in mappedItems) {
var prevItem = mappedItems[itemKey];
if (delete mappedItems[itemKey] && compareItems(prevItem, nextItem)) {
detectedChanges.unchangedItems.push(nextItem);
} else {
detectedChanges.updatedItems.push(nextItem);
}
} else {
detectedChanges.addedItems.push(nextItem);
}
}
for (var itemKey in mappedItems) {
if (itemKey in mappedItems) {
detectedChanges.removedItems.push(mappedItems[itemKey]);
}
}
return detectedChanges;
}
// Usage example:
var prevItems = [
{name: 'John', value: 32}, // Unchanged
{name: 'Kate', value: 21}, // Updated
{name: 'Matt', value: 26}, // Removed
{name: 'Greg', value: 24} // Unchanged
];
var nextItems = [
{name: 'John', value: 32}, // Unchanged
{name: 'Kate', value: 25}, // Updated
{name: 'Chris', value: 40}, // Added
{name: 'Greg', value: 24} // Unchanged
];
var getKey = function(item) {
return item.name;
};
var compareItems = function(a, b) {
return a.name === b.name && a.value === b.value;
};
var detectedChanges = detectChanges(prevItems, nextItems, getKey, compareItems);
console.log('Added items: ' + JSON.stringify(detectedChanges.addedItems, null, 4));
console.log('Updated items: ' + JSON.stringify(detectedChanges.updatedItems, null, 4));
console.log('Removed items: ' + JSON.stringify(detectedChanges.removedItems, null, 4));
console.log('Unchanged items: ' + JSON.stringify(detectedChanges.unchangedItems, null, 4));
ES6+ solution
// ONLINE-RUNNER:browser;
const mapItems = (items, getKey) => {
const map = {};
for (const item of items) {
const key = getKey(item);
if (key in items) {
throw new Error('Item key is duplicated (' + key + ').');
}
map[key] = item;
}
return map;
}
const detectChanges = (prevItems, nextItems, getKey, compareItems) => {
const mappedItems = mapItems(prevItems, getKey);
const addedItems = [];
const updatedItems = [];
const removedItems = [];
const unchangedItems = [];
for (const nextItem of nextItems) {
const itemKey = getKey(nextItem);
if (itemKey in mappedItems) {
const prevItem = mappedItems[itemKey];
if (delete mappedItems[itemKey] && compareItems(prevItem, nextItem)) {
unchangedItems.push(nextItem);
} else {
updatedItems.push(nextItem);
}
} else {
addedItems.push(nextItem);
}
}
for (const itemKey in mappedItems) {
if (itemKey in mappedItems) {
removedItems.push(mappedItems[itemKey]);
}
}
return {addedItems, updatedItems, removedItems, unchangedItems};
}
// Usage example:
const prevItems = [
{name: 'John', value: 32}, // Unchanged
{name: 'Kate', value: 21}, // Updated
{name: 'Matt', value: 26}, // Removed
{name: 'Greg', value: 24} // Unchanged
];
const nextItems = [
{name: 'John', value: 32}, // Unchanged
{name: 'Kate', value: 25}, // Updated
{name: 'Chris', value: 40}, // Added
{name: 'Greg', value: 24} // Unchanged
];
const getKey = (item) => item.name;
const compareItems = (a, b) => a.name === b.name && a.value === b.value;
const detectedChanges = detectChanges(prevItems, nextItems, getKey, compareItems);
console.log('Added items: ' + JSON.stringify(detectedChanges.addedItems, null, 4));
console.log('Updated items: ' + JSON.stringify(detectedChanges.updatedItems, null, 4));
console.log('Removed items: ' + JSON.stringify(detectedChanges.removedItems, null, 4));
console.log('Unchanged items: ' + JSON.stringify(detectedChanges.unchangedItems, null, 4));