本文翻译自:
Remove duplicates from an array of objects in JavaScript
I have an object that contains an array of objects.
我有一个包含对象数组的对象。
things = new Object();
things.thing = new Array();
things.thing.push({place:"here",name:"stuff"});
things.thing.push({place:"there",name:"morestuff"});
things.thing.push({place:"there",name:"morestuff"});
I’m wondering what is the best method to remove duplicate objects from an array.
我想知道什么是从数组中删除重复对象的最佳方法。
So for example, things.thing would become…
举例来说,事物……东西将变成……
{place:"here",name:"stuff"},
{place:"there",name:"morestuff"}
#1楼
参考:
https://stackoom.com/question/9JGJ/从JavaScript中的对象数组中删除重复项
#2楼
A primitive method would be:
一种原始方法是:
var obj = {};
for ( var i=0, len=things.thing.length; i < len; i++ )
obj[things.thing[i]['place']] = things.thing[i];
things.thing = new Array();
for ( var key in obj )
things.thing.push(obj[key]);
#3楼
This is a generic way of doing this: you pass in a function that tests whether two elements of an array are considered equal.
这是执行此操作的通用方法:传递一个函数来测试数组的两个元素是否相等。
In this case, it compares the values of the
name
and
place
properties of the two objects being compared.
在这种情况下,它将比较两个要比较的对象的
name
和
place
属性的值。
ES5 answer
ES5答案
function removeDuplicates(arr, equals) { var originalArr = arr.slice(0); var i, len, j, val; arr.length = 0; for (i = 0, len = originalArr.length; i < len; ++i) { val = originalArr[i]; if (!arr.some(function(item) { return thingsEqual(item, val); })) { arr.push(val); } } } function thingsEqual(thing1, thing2) { return thing1.place === thing2.place && thing1.name === thing2.name; } var things = [ {place:"here",name:"stuff"}, {place:"there",name:"morestuff"}, {place:"there",name:"morestuff"} ]; removeDuplicates(things, thingsEqual); console.log(things);
Original ES3 answer
ES3原始答案
function arrayContains(arr, val, equals) {
var i = arr.length;
while (i--) {
if ( equals(arr[i], val) ) {
return true;
}
}
return false;
}
function removeDuplicates(arr, equals) {
var originalArr = arr.slice(0);
var i, len, j, val;
arr.length = 0;
for (i = 0, len = originalArr.length; i < len; ++i) {
val = originalArr[i];
if (!arrayContains(arr, val, equals)) {
arr.push(val);
}
}
}
function thingsEqual(thing1, thing2) {
return thing1.place === thing2.place
&& thing1.name === thing2.name;
}
removeDuplicates(things.thing, thingsEqual);
#4楼
If you can wait to eliminate the duplicates until after all the additions, the typical approach is to first sort the array and then eliminate duplicates.
如果您要等到所有添加之后才消除重复项,那么典型的方法是先对数组排序,然后消除重复项。
The sorting avoids the N * N approach of scanning the array for each element as you walk through them.
排序避免了在遍历每个元素时使用N * N方法扫描数组中每个元素的方法。
The “eliminate duplicates” function is usually called
unique
or
uniq
.
“消除重复项”功能通常称为
unique
或
uniq
。
Some existing implementations may combine the two steps, eg,
prototype’s uniq
一些现有的实现可以将两个步骤结合起来,例如,
原型的uniq
This post
has few ideas to try (and some to avoid 🙂 )
if your library doesn’t already have one
!
这篇文章
有一些想法,尝试(和一些避免:-))
如果你的库已经没有之一
!
Personally I find this one the most straight forward:
我个人认为这是最直接的方法:
function unique(a){
a.sort();
for(var i = 1; i < a.length; ){
if(a[i-1] == a[i]){
a.splice(i, 1);
} else {
i++;
}
}
return a;
}
// Provide your own comparison
function unique(a, compareFunc){
a.sort( compareFunc );
for(var i = 1; i < a.length; ){
if( compareFunc(a[i-1], a[i]) === 0){
a.splice(i, 1);
} else {
i++;
}
}
return a;
}
#5楼
If you can use Javascript libraries such as
underscore
or lodash, I recommend having a look at
_.uniq
function in their libraries.
如果可以使用
下划线
或lodash之类的Javascript库,建议您查看它们库中的
_.uniq
函数。
From
lodash
:
从
lodash
:
_.uniq(array, [isSorted=false], [callback=_.identity], [thisArg])
Basically, you pass in the array that in here is an object literal and you pass in the attribute that you want to remove duplicates with in the original data array, like this:
基本上,您传入的数组是此处的对象文字,然后传入要删除原始数据数组中重复项的属性,如下所示:
var data = [{'name': 'Amir', 'surname': 'Rahnama'}, {'name': 'Amir', 'surname': 'Stevens'}];
var non_duplidated_data = _.uniq(data, 'name');
UPDATE
: Lodash now has introduced a
.uniqBy
as well.
更新
:Lodash现在也引入了
.uniqBy
。
#6楼
Another option would be to create a custom indexOf function, which compares the values of your chosen property for each object and wrap this in a reduce function.
另一个选择是创建一个自定义indexOf函数,该函数将比较每个对象所选属性的值并将其包装在reduce函数中。
var uniq = redundant_array.reduce(function(a,b){
function indexOfProperty (a, b){
for (var i=0;i<a.length;i++){
if(a[i].property == b.property){
return i;
}
}
return -1;
}
if (indexOfProperty(a,b) < 0 ) a.push(b);
return a;
},[]);