Reputation: 46543
var array1 = [{ "name" : "foo" , "age" : "22"}, { "name" : "bar" , "age" : "33"}];
var array2 = [{ "name" : "foo" , "age" : "22"}, { "name" : "buz" , "age" : "35"}];
What's the fastest way to have (no duplicates, name is the identifier):
[{ "name" : "foo" , "age" : "22"}, { "name" : "bar" , "age" : "33"}, { "name" : "buz" , "age" : "35"}];
With and without jquery if possible.
Upvotes: 1
Views: 715
Reputation: 708026
Here's a general purpose function that would merge an arbitrary number of arrays, preventing duplicates of the passed in key.
As it is merging, it creates a temporary index of the names used so far and only merges new elements that have a unique name. This temporary index should be much faster than a linear search through the results, particularly as the arrays get large. As a feature this scheme, it filters all duplicates, even duplicates that might be in one of the source arrays.
If an element does not have the keyName, it is skipped (though that logic could be reversed if you want depending upon what error handling you want for that):
var array1 = [{ "name" : "foo" , "age" : "22"}, { "name" : "bar" , "age" : "33"}];
var array2 = [{ "name" : "foo" , "age" : "22"}, { "name" : "buz" , "age" : "35"}];
function mergeArrays(keyName /* pass arrays as additional arguments */) {
var index = {}, i, len, merge = [], arr, name;
for (var j = 1; j < arguments.length; j++) {
arr = arguments[j];
for (i = 0, len = arr.length; i < len; i++) {
name = arr[i][keyName];
if ((typeof name != "undefined") && !(name in index)) {
index[name] = true;
merge.push(arr[i]);
}
}
}
return(merge);
}
var merged = mergeArrays("name", array1, array2);
// Returns:
// [{"name":"foo","age":"22"},{"name":"bar","age":"33"},{"name":"buz","age":"35"}]
You can see it work here: http://jsfiddle.net/jfriend00/8WfFW/
When this algorithm is run against the Matt algorithm in jsperf using larger arrays, this algorithm is around 20x faster:
Upvotes: 5
Reputation: 75327
What you have are completely different objects, and there is nothing built into JavaScript to detect identical objects; i.e. objects which have the same attributes, so we have to write our own function:
function merge(set1, set2) {
// Already put the elements of set1 in the result array
// see Array.slice
var result = set1.slice(0);
// Utility function which iterates over the elements in result
// and returns true if an element with the same name already
// exists. false otherwise
function exists(obj) {
for (var i=0;i<result.length;i++) {
if (result[i].name == obj.name) {
return true;
}
}
return false;
}
// Now simply iterate over the second set and add elements
// which aren't there already using our exists() function.
for (var i=0;i<set2.length;i++) {
if (!exists(set2[i])) {
result.push(set2[i]);
}
}
return result;
}
You'd then call it with;
var result = merge(array1, array2);
To become more confident with object equality try the following experiment;
var a = { "test": 1 };
var b = { "test": 1 };
var aClone = a;
alert(a == a); // true
alert(a == b); // false
alert(a == aClone); // true
Upvotes: 1
Reputation: 9359
The first way I can think of:
array3 = [];
for(object in array1) {
var match=false;
for(already in array3) {
if (already==object) {
match=true;
break; } }
if (match) array3.push(object); }
Upvotes: -2
Reputation: 6237
I don't think that plain javascript offers anything better than iterating the array's and manually implementing the logic for that. What I would advice is to use the awesome underscore.js library that provides many functional-like facilities to handle arrays and collections in general; to solve your problem for example this could work:
http://documentcloud.github.com/underscore/#union
jQuery is another option, but it is more a DOM-manipulation browser-oriented library, while underscore is made to deal with these kind of problems.
Upvotes: 0