Reputation: 53
I have 2 arrays:
[{name:'test', lastname: 'test', gender:'f'},{name:'test1', lastname: 'test1', gender:'f'},{name:'test2', lastname: 'test2', gender:'m'}]
[{name:'test21', lastname: 'test21', gender:'f'},{name:'test1', lastname: 'test1', gender:'f'},{name:'test2', lastname: 'test2', gender:'m'},{name:'test22', lastname: 'test22', gender:'m'}]
How to merge these in one array with unique objects (for unique check 'name')?
Upvotes: 0
Views: 112
Reputation: 26191
It's easy if you have an Object method like Object.prototype.compare()
. Lets make it.
Object.prototype.compare = function(o){
var ok = Object.keys(this);
return typeof o === "object" && ok.length === Object.keys(o).length ? ok.every(k => this[k] === o[k]) : false;
};
Object.prototype.compare()
compares two objects for a perfect match of all properties and their values. So unlike the accepted answer we are not comparing a single property but all of them. Now it's a simple reducing task. Let's see
Object.prototype.compare = function(o){
var ok = Object.keys(this);
return typeof o === "object" && ok.length === Object.keys(o).length ? ok.every(k => this[k] === o[k]) : false;
};
var arr1 = [{name:'test', lastname: 'test', gender:'f'},{name:'test1', lastname: 'test1', gender:'f'},{name:'test2', lastname: 'test2', gender:'m'}],
arr2 = [{name:'test21', lastname: 'test21', gender:'f'},{name:'test1', lastname: 'test1', gender:'f'},{name:'test2', lastname: 'test2', gender:'m'},{name:'test22', lastname: 'test22', gender:'m'}],
united = arr1.reduce((p,c) => p.find(f => f.compare(c)) ? p : p.concat(c),arr2);
console.log(JSON.stringify(united));
Upvotes: 0
Reputation: 1
var a = [{name:'test', lastname: 'test', gender:'f'},{name:'test1', lastname: 'test1', gender:'f'},{name:'test2', lastname: 'test2', gender:'m'}];
var b = [{name:'test21', lastname: 'test21', gender:'f'},{name:'test1', lastname: 'test1', gender:'f'},{name:'test2', lastname: 'test2', gender:'m'},{name:'test22', lastname: 'test22', gender:'m'}];
var c = a.filter(a => b.find(b => b.name === a.name) === undefined).concat(b);
console.table(c);
Upvotes: 0
Reputation: 386786
For a new array, you could use an object as hash table for lookup.
var array1 = [{ name: 'test', lastname: 'test', gender: 'f' }, { name: 'test1', lastname: 'test1', gender: 'f' }, { name: 'test2', lastname: 'test2', gender: 'm' }],
array2 = [{ name: 'test21', lastname: 'test21', gender: 'f' }, { name: 'test1', lastname: 'test1', gender: 'f' }, { name: 'test2', lastname: 'test2', gender: 'm' }, { name: 'test22', lastname: 'test22', gender: 'm' }],
result = function (a1, a2) {
function merge(a) {
this[a.name] = this[a.name] || r.push(a);
}
var t = Object.create(null),
r = [];
a1.forEach(merge, t);
a2.forEach(merge, t);
return r;
}(array1, array2);
console.log(result);
ES6
var array1 = [{ name: 'test', lastname: 'test', gender: 'f' }, { name: 'test1', lastname: 'test1', gender: 'f' }, { name: 'test2', lastname: 'test2', gender: 'm' }],
array2 = [{ name: 'test21', lastname: 'test21', gender: 'f' }, { name: 'test1', lastname: 'test1', gender: 'f' }, { name: 'test2', lastname: 'test2', gender: 'm' }, { name: 'test22', lastname: 'test22', gender: 'm' }],
result = function (a1, a2) {
var t = Object.create(null),
r = [],
m = a => t[a.name] = t[a.name] || r.push(a);
a1.forEach(m);
a2.forEach(m);
return r;
}(array1, array2);
console.log(result);
Upvotes: 0
Reputation: 135406
A combination of filter
and find
will work
var a = [{name:'test', lastname: 'test', gender:'f'},{name:'test1', lastname: 'test1', gender:'f'},{name:'test2', lastname: 'test2', gender:'m'}];
var b = [{name:'test21', lastname: 'test21', gender:'f'},{name:'test1', lastname: 'test1', gender:'f'},{name:'test2', lastname: 'test2', gender:'m'},{name:'test22', lastname: 'test22', gender:'m'}];
var c = a.filter(a => b.find(b => b.name === a.name) === undefined).concat(b);
console.table(c);
You could also make a generic uniqueByKey
function
var uniqueByKey = (key, xs)=>
xs.reduce((ys,x)=>
ys.find(y=> y[key] === x[key]) === undefined
? ys.concat([x])
: ys,
[]);
var a = [{name:'test', lastname: 'test', gender:'f'},{name:'test1', lastname: 'test1', gender:'f'},{name:'test2', lastname: 'test2', gender:'m'}];
var b = [{name:'test21', lastname: 'test21', gender:'f'},{name:'test1', lastname: 'test1', gender:'f'},{name:'test2', lastname: 'test2', gender:'m'},{name:'test22', lastname: 'test22', gender:'m'}];
var c = uniqueByKey('name', a.concat(b));
console.table(c);
If you're dealing with particularly large datasets, using a Set
cache instead of Array.prototype.find
might be better.
var uniqueByKey = (key, xs)=>
xs.reduce(([set, ys], x)=>
set.has(x[key])
? [set, ys]
: [set.add(x[key]), ys.concat([x])]
, [new Set, []]
) [1];
var a = [{name:'test', lastname: 'test', gender:'f'},{name:'test1', lastname: 'test1', gender:'f'},{name:'test2', lastname: 'test2', gender:'m'}];
var b = [{name:'test21', lastname: 'test21', gender:'f'},{name:'test1', lastname: 'test1', gender:'f'},{name:'test2', lastname: 'test2', gender:'m'},{name:'test22', lastname: 'test22', gender:'m'}];
var c = uniqueByKey('name', a.concat(b));
console.table(c);
Upvotes: 4
Reputation: 40850
What you can do to check duplicate elements the fastest method is to add all elements to an object with the name that you want as key, because accessing the keys is very fast:
var unified = {},
unifiedArray = [],
first = [{name:'test', lastname: 'test', gender:'f'},{name:'test1', lastname: 'test1', gender:'f'},{name:'test2', lastname: 'test2', gender:'m'}],
second = [{name:'test21', lastname: 'test21', gender:'f'},{name:'test1', lastname: 'test1', gender:'f'},{name:'test2', lastname: 'test2', gender:'m'},{name:'test22', lastname: 'test22', gender:'m'}],
addToUnified = function(obj) {
if (unified[obj.name]) {
alert('duplicate detected!\n' + JSON.stringify(obj) + '\n' + ' has same name as\n' + JSON.stringify(unified[obj.name]));
} else {
unifiedArray.push(obj);
unified[obj.name] = obj;
}
}
first.forEach(addToUnified);
second.forEach(addToUnified);
If you just want to get a report you don't need the unifiedArray
. If you don't need the report just eliminate the alert
Upvotes: 0
Reputation: 8193
var arr1 = [{name:'test', lastname: 'test', gender:'f'},{name:'test1', lastname: 'test1', gender:'f'},{name:'test2', lastname: 'test2', gender:'m'}]
var arr2 = [{name:'test', lastname: 'test', gender:'f'},{name:'test21', lastname: 'test21', gender:'f'},{name:'test1', lastname: 'test1', gender:'f'},{name:'test2', lastname: 'test2', gender:'m'},{name:'test22', lastname: 'test22', gender:'m'}]
var newArray =arr1.concat(arr2);
var unique = {};
var result = [];
newArray.forEach(function (elem) {
if (!unique[elem.name]) {
result.push(elem);
unique[elem.name] = true;
}
});
console.log(result);
document.write(JSON.stringify(result));
Upvotes: 1