如何在javascripts中获取唯一的对象数组

时间:2013-06-03 09:19:34

标签: javascript jquery arrays

我想获得具有唯一对象的数组。

说我有对象数组

[{"a":"b"},{"c":"d"},{"a":"b"}] 

我想要数组的唯一值,即

[{"a":"b"},{"c":"d"}]

有没有最简单的方法来做到这一点。

2 个答案:

答案 0 :(得分:7)

如果一遍又一遍地包含相同对象的数组,你可以做这样的函数:

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;
}

请注意,某些方法的使用取决于ECMAScript第5版:

Array.some
Array.indexOf

答案 1 :(得分:4)

最简单的选择是通过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来获取此类内容,有关更多讨论和示例,请参阅Check if duplicate array pairs exist using underscore only

一些评论者提出了一个问题,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以接受关键功能:

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}]