我想获得具有唯一对象的数组。
说我有对象数组
[{"a":"b"},{"c":"d"},{"a":"b"}]
我想要数组的唯一值,即
[{"a":"b"},{"c":"d"}]
有没有最简单的方法来做到这一点。
我想获得具有唯一对象的数组。
说我有对象数组
[{"a":"b"},{"c":"d"},{"a":"b"}]
我想要数组的唯一值,即
[{"a":"b"},{"c":"d"}]
有没有最简单的方法来做到这一点。
如果数组一遍又一遍地包含相同的对象,你可以做一个这样的函数:
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;
}
但这很可能不起作用,因为即使它们接缝相同,对象也是不同的:
alert( {a: 1} === {a: 1} ); // false
但:
var a = {a: 1};
alert( a === a ); // true
甚至这将是真的:
var a = {a: 1},
b = a;
alert( a === b ); // true
因此,您还必须对此进行测试(这是一个浅薄的描述。一级对象):
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;
}
我们还必须重写我们独特的函数:
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;
}
最简单的选择是通过对象的 JSON 表示来比较对象:
uniq = function(xs) {
var seen = {};
return xs.filter(function(x) {
var key = JSON.stringify(x);
return !(key in seen) && (seen[key] = x);
});
}
例如:
console.log(
uniq([{"a":"b"},{"c":"d"},{"a":"b"},{"a":"b"}])
)
// [{"a":"b"},{"c":"d"}]
此外,我推荐使用 underscore.js 来处理这类内容,请参阅使用下划线检查是否存在重复的数组对,以获取更多讨论和示例。
一些评论者提出了一个问题,JSON.stringify
即在比较仅按键顺序不同的对象时是不充分的。我想这归结为“平等”的定义:{a:1,b:2}
并且{b:2,a:1}
在一种情况下可能被认为是平等的,而在另一种情况下则不同。不过,如果您希望这些对象“相等”,您可以扩展JSON.stringify
为如下所示:
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
);
}
然后修改uniq
接受key函数:
uniq = function(xs, key) {
var seen = {};
return xs.filter(function(x) {
var k = (key || JSON.stringify)(x);
return !(k in seen) && (seen[k] = 1);
});
}
并且,最后将自定义序列化程序传递给uniq
:
console.log(
uniq([
{"a":1, "b":2},
{"x":33},
{"b":2, "a":1},
], toSortedJSON)
)
// [{"a":1,"b":2},{"x":33}]