patternjavascriptModerate
Comparing two arrays to see if they contain objects with different IDs
Viewed 0 times
arrayscomparingobjectscontainwithidsseedifferenttwothey
Problem
This feels like the kind of problem that has an extremely elegant solution. But my code is mechanical and straightforward. Not bad but I'm interested if there's something nicer.
Performance is not really an issue. I'm looking for elegant/shorter, not faster.
No underscore.js please; it's not worth fighting my coworkers to get another third-party library in there, especially when it duplicates so much ES5. Speaking of which, we work in an ES5-only environment so use all the array extras you want.
Performance is not really an issue. I'm looking for elegant/shorter, not faster.
No underscore.js please; it's not worth fighting my coworkers to get another third-party library in there, especially when it duplicates so much ES5. Speaking of which, we work in an ES5-only environment so use all the array extras you want.
function getIds(array) {
// We have added `Array.prototype.unique`; it does what you'd expect.
return array.map(function (x) { return x.id; }).unique().sort();
}
function areDifferentByIds(a, b) {
var idsA = getIds(a);
var idsB = getIds(b);
if (idsA.length !== idsB.length) {
return true;
}
for (var i = 0; i < idsA.length; ++i) {
if (idsA[i] !== idsB[i]) {
return true;
}
}
return false;
}Solution
function areDifferentByIds(a, b) {
var idsA = a.map( function(x){ return x.id; } ).unique().sort();
var idsB = b.map( function(x){ return x.id; } ).unique().sort();
return (idsA.join(',') !== idsB.join(',') );
}This is the simplest I could make it. I think such small functions need to be as self contained as possible, and not need other functions. This makes them more readable, maintainable, and of course reusable. I therefor removed the getIds function. If you use that elsewhere you can keep it.
You might want to store the
function (x) { return x.id; } inside a variable, and reuse it on both mapsI also think it is faster, because join is quite fast, and it doesn't require a for-loop.
EDIT my next attempt
function areDifferentByIds(a, b) {
var idsA = a.map( function(x){ return x.id; } ).unique();
var idsB = b.map( function(x){ return x.id; } ).unique();
var idsAB = a.concat(b).unique();
return idsAB.length!==idsA.length
}secondly, you could make it more generic, by adding the property you want to check to the arguments of the function. Something like:
function areDifferentByProperty(a, b, prop) {
var idsA = a.map( function(x){ return x[prop]; } ).unique();
var idsB = b.map( function(x){ return x[prop]; } ).unique();
var idsAB = a.concat(b).unique();
return idsAB.length!==idsA.length
}thirdly, I would much rather name it areEqualBy___. Seems more intuitive to me, but that's just me.
Code Snippets
function areDifferentByIds(a, b) {
var idsA = a.map( function(x){ return x.id; } ).unique().sort();
var idsB = b.map( function(x){ return x.id; } ).unique().sort();
return (idsA.join(',') !== idsB.join(',') );
}function areDifferentByIds(a, b) {
var idsA = a.map( function(x){ return x.id; } ).unique();
var idsB = b.map( function(x){ return x.id; } ).unique();
var idsAB = a.concat(b).unique();
return idsAB.length!==idsA.length
}function areDifferentByProperty(a, b, prop) {
var idsA = a.map( function(x){ return x[prop]; } ).unique();
var idsB = b.map( function(x){ return x[prop]; } ).unique();
var idsAB = a.concat(b).unique();
return idsAB.length!==idsA.length
}Context
StackExchange Code Review Q#9241, answer score: 12
Revisions (0)
No revisions yet.