HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptModerate

Comparing two arrays to see if they contain objects with different IDs

Submitted by: @import:stackexchange-codereview··
0
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.

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 maps

I 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.