Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 18.05.2012, 20:21
Аватар для FINoM
Новичок
Отправить личное сообщение для FINoM Посмотреть профиль Найти все сообщения от FINoM
 
Регистрация: 05.09.2010
Сообщений: 2,298

Удаление дубликатов в массиве объектов по уникальному ключу
У меня есть массив объектов:
[{id:3}, {id:5}, {id:3}]
Нужно из этого массива убрать дубликаты. Как это вижу я:
ids = [];
array.forEach(function( object ){
  if( ~ids.indexOf(object.id) ) {
    // удаляем сплайсом этот object из массива
  } else {
     ids.push(object.id);
  }
});
Я не уверен, что алгоритм оптимален. Есть ли более оптимальные пути удалять объекты с дублирующимся значением ключа?

UPD Здесь forEach неуместен, нужно юзать обычный for, но это замечание сути дела не меняет
__________________
"Matreshka is fucking awesome" © чувак с Reddit
Matreshka.js - Три возможности
Ответить с цитированием
  #2 (permalink)  
Старый 18.05.2012, 20:45
Аватар для 9xakep
сегодня в 12:34|Комментир
Отправить личное сообщение для 9xakep Посмотреть профиль Найти все сообщения от 9xakep
 
Регистрация: 12.04.2011
Сообщений: 1,180

FINoM,
конечно через жопу сделан, но если выложишь свой код, то можно проверить по скорости:
<script>
var arr = [{id:3}, {id:5}, {id:3}]
var arr2 = []
for(i=0;i<arr.length;i++) {
  for(k=0;k<arr.length;k++) {
    if(k!=i) {
      if(arr[i].id==arr[k].id) arr[k]=''
    }
  }
}
for(i=0;i<arr.length;i++) {
  if(arr[i]=='') continue
  else arr2.push(arr[i])
}
console.log(arr2)
__________________
оляля, ололо
Ответить с цитированием
  #3 (permalink)  
Старый 18.05.2012, 21:14
Аватар для FINoM
Новичок
Отправить личное сообщение для FINoM Посмотреть профиль Найти все сообщения от FINoM
 
Регистрация: 05.09.2010
Сообщений: 2,298

9xakep, ужас. Это в несколько раз хуже моего варианта.
__________________
"Matreshka is fucking awesome" © чувак с Reddit
Matreshka.js - Три возможности
Ответить с цитированием
  #4 (permalink)  
Старый 19.05.2012, 04:39
Аватар для Gvozd
Матрос
Отправить личное сообщение для Gvozd Посмотреть профиль Найти все сообщения от Gvozd
 
Регистрация: 04.04.2008
Сообщений: 6,246

Maxmaxmахimus,
у вас сложность O(N*N)
есть гораздо более быстрый вариант - O(N*lg N) - сперва отстортировать, а затем перенести в новый массив оставив только один из подряд идущих одинаковых
var arr = [1, 2, 3, 1, 2, 3, 5];

var newArr = arr.sort().reduce(function(arr, el){
	if(!arr.length || arr.length && arr[arr.length - 1] != el) {
		arr.push(el);
	}
	return arr;
}, []);

console.log( newArr );


var arr = [{id:3}, {id:5}, {id:3}];

var newArr = arr.sort(function(a,b){return a.id < b.id ? -1 : 1;}).reduce(function(arr, el){
	if(!arr.length || arr[arr.length - 1].id != el.id) {
		arr.push(el);
	}
	return arr;
}, []);

console.log( newArr );
Ответить с цитированием
  #5 (permalink)  
Старый 19.05.2012, 05:41
Аватар для FINoM
Новичок
Отправить личное сообщение для FINoM Посмотреть профиль Найти все сообщения от FINoM
 
Регистрация: 05.09.2010
Сообщений: 2,298

Сообщение от Gvozd
O(N*lg N)
Откуда такая оценка? Только сортировка (исходя из списка алгоритмов на википедии) занимает столько.
__________________
"Matreshka is fucking awesome" © чувак с Reddit
Matreshka.js - Три возможности
Ответить с цитированием
  #6 (permalink)  
Старый 19.05.2012, 05:55
Аватар для FINoM
Новичок
Отправить личное сообщение для FINoM Посмотреть профиль Найти все сообщения от FINoM
 
Регистрация: 05.09.2010
Сообщений: 2,298

Gvozd, сортировка, к сожалению, не подходит. Я подгружаю данные порциями из элементов с произвольными айдишниками и вывожу их. Сортировка потребует перерисовывать каждый раз интерфейс, вместо обычного дописывания ниже. Это не приемлемо в задаче.
Сообщение от Maxmaxmахimus
var someOne = newArr.some(function(el2){return el['id'] === el2['id']});
indexOf (из моего варианта) побыстрее будет.

Другой вопрос. Что быстрее: удалять совпадения (сплайсом) или пихать уникальные объекты в новый массив?
__________________
"Matreshka is fucking awesome" © чувак с Reddit
Matreshka.js - Три возможности
Ответить с цитированием
  #7 (permalink)  
Старый 19.05.2012, 09:33
Аватар для nerv_
junior
Отправить личное сообщение для nerv_ Посмотреть профиль Найти все сообщения от nerv_
 
Регистрация: 29.11.2011
Сообщений: 3,924

Сообщение от FINoM
Что быстрее: удалять совпадения (сплайсом) или пихать уникальные объекты в новый массив?
на первый взгляд ответ очевиден -
Сообщение от FINoM
пихать уникальные объекты в новый массив
__________________
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук
Ответить с цитированием
  #8 (permalink)  
Старый 19.05.2012, 09:48
Аватар для B@rmaley.e><e
⊞ Развернуть
Отправить личное сообщение для B@rmaley.e><e Посмотреть профиль Найти все сообщения от B@rmaley.e><e
 
Регистрация: 11.01.2010
Сообщений: 1,810

Сообщение от FINoM
Откуда такая оценка? Только сортировка (исходя из списка алгоритмов на википедии) занимает столько.
O(N lg N) + O(N) = O(N lg N)
Ответить с цитированием
  #9 (permalink)  
Старый 19.05.2012, 11:15
sinistral
Посмотреть профиль Найти все сообщения от melky
 
Регистрация: 28.03.2011
Сообщений: 5,418

про новые методы все забыли ? Array.prototype.filter легко реализуется в IE, а сама проверка существование через in - самая быстрая операция в JS (на хабрэ читал исследование)
нужна проверка по ID, а это примитив... как раз сюда подойдет оператор in.
var used = {};

var arr = [{id:3}, {id:5}, {id:3}, {id:3}, {id:3}, {id:7}, {id:7}];

var filtered = arr.filter(function(obj) {
    return obj.id in used ? 0:(used[obj.id]=1);
    /*
    var res = !(obj.id in used);
    used[obj.id] = null;
    return res;
    */
});

console.log(filtered);



Сообщение от FINoM Посмотреть сообщение
Другой вопрос. Что быстрее: удалять совпадения (сплайсом) или пихать уникальные объекты в новый массив?
сплайс будет сдвигать все последующие значения, заполняя просвет. очень медленно

Последний раз редактировалось melky, 19.05.2012 в 11:21.
Ответить с цитированием
  #10 (permalink)  
Старый 19.05.2012, 13:12
sinistral
Посмотреть профиль Найти все сообщения от melky
 
Регистрация: 28.03.2011
Сообщений: 5,418

Сообщение от Maxmaxmахimus
но это так криво выглядит что я сделал обычный перебор.
что там кривого?

FINoM свой код не написал. (запускаемый пример)

Пример: Gvozd
var arr, i, c, st;
for(i = 0, c = 1e4, arr = []; i < c; i += 1) arr.push({ id: i > c/2 ? i:c-i }); 
st = Date.now();

var newArr = arr.sort(function(a,b){return a.id < b.id ? -1 : 1;}).reduce(function(arr, el){
	if(!arr.length || arr[arr.length - 1].id != el.id) {
		arr.push(el);
	}
	return arr;
}, []);

console.log("Gvozd", Date.now() - st);


у кода 9xakep тот же принцип, что и у кода Maxmaxmахimus, только у последнего исп-ся быстрые функции, реализованные в движке. (или я по диагонали его код прочитал?)
Пример: Maxmaxmахimus
var arr, i, c, st;
for(i = 0, c = 1e4, arr = []; i < c; i += 1) arr.push({ id: i > c/2 ? i:c-i }); 
st = Date.now();

var newArr = [];
arr.forEach(function(el){
  var someOne = newArr.some(function(el2){return el['id'] === el2['id']});
  if( !someOne ) {
    newArr.push(el);
  }
});

console.log("Maxmaxmахimus", Date.now() - st);



Пример: melky
var arr, i, c, st;
for(i = 0, c = 1e4, arr = []; i < c; i += 1) arr.push({ id: i > c/2 ? i:c-i }); 
st = Date.now();

var used = {};
var filtered = arr.filter(function(obj) {
    return obj.id in used ? 0:(used[obj.id]=1);
});

console.log("melky", Date.now() - st);

Последний раз редактировалось melky, 19.05.2012 в 13:52.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
удаление объектов и тонкая работа с ними(помогите) digitalbrain Общие вопросы Javascript 4 28.07.2010 21:17