У меня есть объект, который содержит массив объектов.
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"});
Я задаюсь вопросом, что является лучшим методом для удаления дублирующихся объектов из массива. Так, например, things.thing стал бы...
{place:"here",name:"stuff"},
{place:"there",name:"morestuff"}
Примитивным методом будет:
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]);
Если вы можете подождать, чтобы удалить дубликаты до завершения всех добавлений, типичный подход состоит в том, чтобы сначала отсортировать массив, а затем удалить дубликаты. Сортировка позволяет избежать подхода N * N, когда вы просматриваете массив для каждого элемента.
Функция «удаления дубликатов» обычно называется unique или uniq . Некоторые существующие реализации могут комбинировать эти два шага, например, uniq прототипа
В этом сообщении есть несколько идей, которые стоит попробовать (и некоторых, которых следует избегать :-)) , если в вашей библиотеке их еще нет ! Лично я считаю, что это самый простой:
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;
}
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.
ES5 answer
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
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);