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.
-
Yes, probably there is.Matteo Tassinari– Matteo Tassinari2013年06月03日 09:21:22 +00:00Commented Jun 3, 2013 at 9:21
-
1There's no simple way of doing it - you'll need to do it by hand. Start by writing a comparator function, which takes 2 objects and returns true/false based on whether the objects are equal. Then loop over the array with this comparator.Aleks G– Aleks G2013年06月03日 09:21:39 +00:00Commented Jun 3, 2013 at 9:21
-
1It is not a dupe, there you had a fixed property that you could lookup, here you don't.BrunoLM– BrunoLM2013年06月03日 09:26:44 +00:00Commented Jun 3, 2013 at 9:26
-
1@harsha This is not the same question. In your linked question, the duplicity is checked by one specific key. Here the set of properties is not fixed for any of the objects and all of them must be equal.Aleks G– Aleks G2013年06月03日 09:28:38 +00:00Commented Jun 3, 2013 at 9:28
-
Sorry guys,my bad,posted the wrong link.Will remove it.Harsha Venkataramu– Harsha Venkataramu2013年06月03日 09:29:57 +00:00Commented Jun 3, 2013 at 9:29
2 Answers 2
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;
}
Full Code:
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;
}
Note the use of some methods is depending on ECMAScript 5th Edition:
Comments
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}]
5 Comments
{'a': 'b', 'c': 'd'} and {'c': 'd', 'a': 'b'} are practically the same object, but the JSON representations may not be the same.{a: 1, b: 1} and {b: 1, a: 1} is stringified the same way?