给定一组对象:
var arr = [
{a: "foo", b: "bar", c: "baz" },
{a: "foo", b: "bar", c: "qux" },
{a: "foo", b: "bar", c: "baz" },
{a: "foo", b: "bar", c: "qux" },
{a: "bar", b: "foo", c: "qux" },
{a: "bar", b: "qux", c: "foo" },
{a: "bar", b: "foo", c: "qux" }
];
应过滤数组,以便只保留唯一对象:
var arr = [
{a: "foo", b: "bar", c: "baz" },
{a: "foo", b: "bar", c: "qux" },
{a: "bar", b: "foo", c: "qux" },
{a: "bar", b: "qux", c: "foo" }
];
对于普通字符串数组,我使用
arr.filter(function (value, index, self) {
return self.indexOf(value) === index;
}
但这并不适用于对象。在我的情况下,必须比较所有属性。我想需要进行某种深度比较?
答案 0 :(得分:0)
如果你的对象都有相同的键,你可以使用lodash或下划线的_.findWhere
函数:
在集合中的每个元素与源对象之间执行深度比较,返回具有等效属性值的第一个元素。
var arr = [
{a: "foo", b: "bar", c: "baz" },
{a: "foo", b: "bar", c: "qux" },
{a: "foo", b: "bar", c: "baz" },
{a: "foo", b: "bar", c: "qux" },
{a: "bar", b: "foo", c: "qux" },
{a: "bar", b: "qux", c: "foo" },
{a: "bar", b: "foo", c: "qux" }
];
function uniqueObjects(arr) {
var u = [];
arr.forEach(function(obj) {
if (!_.findWhere(u, obj)) {
u.push(obj);
}
});
return u
}
document.getElementById('result').innerHTML = JSON.stringify(uniqueObjects(arr),null,2);
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.7.0/lodash.min.js"></script>
<pre id='result'></pre>
如果没有,可以通过两种方式使用_.matches
进行深入比较:
var arr = [
{a: "foo", b: "bar", c: "baz" },
{a: "foo", b: "bar", c: "qux" },
{a: "foo", b: "bar", c: "baz" },
{a: "foo", b: "bar", c: "qux" },
{a: "bar", b: "foo", c: "qux" },
{a: "bar", b: "qux", c: "foo" },
{a: "bar", b: "foo", c: "qux" },
// Missing property
{a: "foo", b: "bar" },
// Ordering
{a: "foo", c: "qux" },
{c: "qux", a: "foo" }
];
function uniqueObjects(arr) {
var u = [];
arr.forEach(function(obj) {
if (!u.filter(deepCompare(obj)).length) {
u.push(obj);
}
});
return u;
}
function deepCompare(obj) {
return function(source) {
return _.matches(obj)(source) && _.matches(source)(obj);
};
}
document.getElementById('result').innerHTML = JSON.stringify(uniqueObjects(arr),null,2);
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.7.0/lodash.min.js"></script>
<pre id='result'></pre>
答案 1 :(得分:-2)
我使用了我在评论中提到的方法。
var arr = [
{c: "baz", a: "foo", b: "bar" },
{c: "qux", a: "foo", b: "bar" },
{c: "baz", b: "bar", a: "foo" },
{c: "qux", b: "bar", a: "foo" },
{a: "bar", c: "qux", b: "foo" },
{a: "bar", c: "foo", b: "qux" },
{a: "bar", b: "foo", c: "qux" }
];
var modified = arr.map(function (value) {
var result = [];
var keys = Object.keys(value).sort();
for (var i = 0; i < keys.length; i++) {
result.push(value[keys[i]]);
}
return result.join('');
});
for (var i = (modified.length - 1); i >= 0; i--) {
if (modified.indexOf(modified[i]) !== i) {
arr.splice(i, 1);
}
}
alert(JSON.stringify(arr));
&#13;
答案 2 :(得分:-3)
使用lodash! https://lodash.com/docs#uniq
创建一个无副本版本的数组,使用SameValueZero进行相等比较,其中只保留每个元素的第一个出现位置。为isSorted提供true为排序数组执行更快的搜索算法。如果提供了iteratee函数,则为数组中的每个元素调用它以生成计算唯一性的标准。 iteratee绑定到thisArg并使用三个参数调用:(value,index,array)。
将其包含在您的HTML中
<script src="bower_components/lodash/lodash.js"></script>
然后在你的控制器中。
var filteredArray = _.uniq(arr, function(item, key, a) {
return item.a;
});