I want to get array having unique objects.
Say I have array of objects
[{"a":"b"},{"c":"d"},{"a":"b"}]
and I want unique value of array i.e
[{"a":"b"},{"c":"d"}]
is there any simplest way to do this.
If the array containing the same objects over and over again you can do make a function like this:
var oa = {"a":"b"},
ob = {"c":"d"};
var array = [oa, ob, oa];
function unique(a) {
var arr = [];
for(var i = 0; i < a.length; i++) {
if( !arr.indexOf(a[i]) == -1 ) {
arr.push(a[i]);
}
}
return arr;
}
But this will most likely not work because the object even when they seams the same is different:
alert( {a: 1} === {a: 1} ); // false
But:
var a = {a: 1};
alert( a === a ); // true
And even this will be true:
var a = {a: 1},
b = a;
alert( a === b ); // true
So you will have to test for that as well (this is a shallow caparation. One level objects):
function isEqual(a, b) {
var prop;
for( prop in a ) {
if ( a[prop] !== b[prop] ) return false;
}
for( prop in b ) {
if ( b[prop] !== a[prop] ) return false;
}
return true;
}
And we have to rewrite our unique function as well:
function unique(a) {
var isAdded,
arr = [];
for(var i = 0; i < a.length; i++) {
isAdded = arr.some(function(v) {
return isEqual(v, a[i]);
});
if( !isAdded ) {
arr.push(a[i]);
}
}
return arr;
}
var a = [{"a":"b"},{"c":"d"},{"a":"b"}],
b = unique(a); // [{"a":"b"},{"c":"d"}]
function unique(a) {
var isAdded,
arr = [];
for(var i = 0; i < a.length; i++) {
isAdded = arr.some(function(v) {
return isEqual(v, a[i]);
});
if( !isAdded ) {
arr.push(a[i]);
}
}
return arr;
}
function isEqual(a, b) {
var prop;
for( prop in a ) {
if ( a[prop] !== b[prop] ) return false;
}
for( prop in b ) {
if ( b[prop] !== a[prop] ) return false;
}
return true;
}
Array.some
Array.indexOf
The simplest option is to compare objects by their JSON representation:
uniq = function(xs) {
var seen = {};
return xs.filter(function(x) {
var key = JSON.stringify(x);
return !(key in seen) && (seen[key] = x);
});
}
For example:
console.log(
uniq([{"a":"b"},{"c":"d"},{"a":"b"},{"a":"b"}])
)
// [{"a":"b"},{"c":"d"}]
Also, I recommend underscore.js for this kind of stuff, see Check if duplicate array pairs exist using underscore only for more discussion and examples.
Some commenters raised a concern that JSON.stringify
is inadequate when comparing objects that differ only by the order of keys. I guess that comes down to the definition of "equality": {a:1,b:2}
and {b:2,a:1}
might be considered equal in one context and different in another. Still, if you want such objects to be "equal", you can extend JSON.stringify
to be something like this:
toSortedJSON = function(obj) {
return JSON.stringify(
typeof obj == "object" ?
Object.keys(obj).sort().reduce(function(o, key) {
return o[key] = toSortedJSON(obj[key]), o;
}, {}) : obj
);
}
Then modify uniq
to accept the key function:
uniq = function(xs, key) {
var seen = {};
return xs.filter(function(x) {
var k = (key || JSON.stringify)(x);
return !(k in seen) && (seen[k] = 1);
});
}
and, finally pass the custom serializer to uniq
:
console.log(
uniq([
{"a":1, "b":2},
{"x":33},
{"b":2, "a":1},
], toSortedJSON)
)
// [{"a":1,"b":2},{"x":33}]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With