Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Union of Array of Objects in JavaScript?

Tags:

javascript

So after searching the interwebz for a few hours I have not found the solution I am looking for.

I have two arrays that contain game objects with a lot of information inside. (e.g. title, slug, thumbnail, summary, genre, release date...).

The Array 1 is a collection of objects that match user's interests specified during the registration.

The Array 2 is a collection of objects that match purchased games of similar users. (Similar users are those that share common interests)

Problem: It is possible, and what is happening in my case, there are two identical games - the game in Array 1 is also in Array 2. In the first array the game is there because it matches user's interests. In the second array the game is there because a similar user has bought that game.

Question: Underscore.js has a nice little function union() http://underscorejs.org/#union that gives you a union of two arrays, but it does not work with an array of objects, only on primitive values. How could I make it work give me a union of array of objects?

like image 983
Sahat Yalkabov Avatar asked Nov 10 '12 04:11

Sahat Yalkabov


People also ask

How do you combine two objects in an array?

concat is the proper way to merge 2 arrays into one.

What is [] vs {} in JS?

[] is declaring an array. {} is declaring an object. An array has all the features of an object with additional features (you can think of an array like a sub-class of an object) where additional methods and capabilities are added in the Array sub-class.

What is Union in JavaScript?

Union() method belongs to underscore. js a library of javascript. The _. union() function is used to take n number of arrays and return a new array with the unique terms in all those arrays (union of all array). It scrutinizes each and every value of the arrays and pushes out unique values into another array.

What is array Union?

Union of arrays would represent a new array combining all elements of the input arrays, without repetition of elements.


2 Answers

You could implement your own pretty easily. In this case, we make the function generic, so that it can take arrays of any data type(s) and union them using the comparator function provided.

// arr1 and arr2 are arrays of any length; equalityFunc is a function which
// can compare two items and return true if they're equal and false otherwise
function arrayUnion(arr1, arr2, equalityFunc) {
    var union = arr1.concat(arr2);

    for (var i = 0; i < union.length; i++) {
        for (var j = i+1; j < union.length; j++) {
            if (equalityFunc(union[i], union[j])) {
                union.splice(j, 1);
                j--;
            }
        }
    }

    return union;
}

function areGamesEqual(g1, g2) {
    return g1.title === g2.title;
}

// Function call example
arrayUnion(arr1, arr2, areGamesEqual);

Refer to Object comparison in JavaScript for various object comparison implementations.

like image 187
Chris Hayes Avatar answered Oct 13 '22 00:10

Chris Hayes


You can do it using the underscore way:

// collectionUnion(*arrays, iteratee)
function collectionUnion() {
    var args = Array.prototype.slice.call(arguments);
    var it = args.pop();

    return _.uniq(_.flatten(args, true), it);
}

It just an improvment of the original function _.union(*arrays), adding an iteratee to work collection (array of object).

Here how to use it:

var result = collectionUnion(a, b, c, function (item) {
    return item.id;
});

The original function which is just working with array, looks like that:

_.union = function() {
  return _.uniq(flatten(arguments, true, true));
};

And in bonus a full example:

// collectionUnion(*arrays, iteratee)
function collectionUnion() {
    var args = Array.prototype.slice.call(arguments);
    var it = args.pop();

    return _.uniq(_.flatten(args, true), it);
}

var a = [{id: 0}, {id: 1}, {id: 2}];
var b = [{id: 2}, {id: 3}];
var c = [{id: 0}, {id: 1}, {id: 2}];

var result = collectionUnion(a, b, c, function (item) {
    return item.id;
});

console.log(result); // [ { id: 0 }, { id: 1 }, { id: 2 }, { id: 3 } ]
like image 28
Arnaud Valensi Avatar answered Oct 12 '22 23:10

Arnaud Valensi