2014-08-19 3 views
0

У меня есть массив объектов в таком виде:Javascript: объекты с уникальным ключом в массиве

[ 
    { id:"123", url:"example1.com"}, 
    { id:"123", url:"example2.com"}, 
    { id:"456", url:"example3.com"}, 
    { id:"789", url:"example4.com"}, 
] 

Я ищу быстро исполняющий способ фильтровать этот массив, чтобы сохранить только объекты с уникальным идентификатором в этом случае, вывод должен быть:

[ 
    { id:"123", url:"example1.com"}, 
    { id:"456", url:"example3.com"}, 
    { id:"789", url:"example4.com"}, 
] 

Я использую двойной цикл для сравнения моих объектов, но это мучительно медленно на большом массиве ... кто-нибудь есть хорошее решение?

+0

Используйте 'id' как индекс для массива вместо этого? 'arr [456] = ...'? Предположительно идентификатор id ==, который является уникальным – CodingIntrigue

+0

Пожалуйста, добавьте код своего двойного цикла, чтобы быть уверенным в том, что вы просите. – Volune

+0

Невозможно ли выполнить предварительную обработку, чтобы ваш вход не был отформатирован так, как в первую очередь? ex: Создание идентификаторов из хэширования и хранения в словаре. –

ответ

1

Вы можете использовать Array.filter (см MDN), что-то вроде

var filtered = [ 
    { id:"123", url:"example1.com"}, 
    { id:"123", url:"example2.com"}, 
    { id:"456", url:"example3.com"}, 
    { id:"789", url:"example4.com"}, 
    ].filter(function (v) { 
       return !this[v.id] ? (this[v.id] = true) : false; }, 
      {}); 
+0

Какой смысл использовать '((this [v.id] = true), true)' вместо просто '(this [v.id] = true)' – 0101

+0

Ничего вообще;). Удалили. – KooiInc

3

Смотрите эту скрипку: http://jsfiddle.net/afnvqj49/

Я использую только один для цикла и экономии уже обработанных ключей в объекте.

var a = [ 
    { id:"123", url:"example1.com"}, 
    { id:"123", url:"example2.com"}, 
    { id:"456", url:"example3.com"}, 
    { id:"789", url:"example4.com"}, 
]; 

var b = []; 
var t = {}; 
for(var i = 0; i < a.length; i++){ 
    if(t[a[i].id]){ 
     continue; 
    } 
    t[a[i].id] = true; 
    b.push(a[i]); 
} 

console.log(b); 

Только первая запись для каждого идентификатора хранится

0
window.idHolder = []; //its better not to use window object and instead use bind. 
var arr = [ 
    { id:"123", url:"example1.com}, 
    { id:"123", url:"example2.com}, 
    { id:"456", url:"example3.com}, 
    { id:"789", url:"example4.com}, 
]; 

var uniqueArr = arr.filter(function(val) 
{ 
if(window.idHolder.indexOf(val.id)!=-1) 
{ 
return false; 
} 
else 
{ 
window.idHolder.push(val.id); 
return true; 
} 

}); 

Unique обр будет иметь то, что вы просили

2
var distinct = function(input, keyExtractor){ 
    var seen = {}, result = []; 
    for(var i = 0, l = input.length; i < l; ++i){ 
     var key = keyExtractor(input[i]); 
     if(seen.hasOwnProperty(key)) { 
     continue; 
     } 
     result.push(input[i]); 
     seen[key] = 1; 
    } 
    return result; 
} 

var test = [ 
     { id:"123", url:"example1.com"}, 
     { id:"123", url:"example2.com"}, 
     { id:"456", url:"example3.com"}, 
     { id:"789", url:"example4.com"}, 
    ]; 

var u = distinct(test, function(a) { return a.id; }); 
1
var reserved = []; 
var arr = [ 
    { id:"123", url:"example1.com"}, 
    { id:"123", url:"example2.com"}, 
    { id:"456", url:"example3.com"}, 
    { id:"789", url:"example4.com"}, 
]; 

var result = arr.filter(function(item) { 
    var has = ~reserved.indexOf(item.id); 
    (!has && reserved.push(item.id)); 
    return !has; 
}); 
0

Поскольку есть много хороших ответов, я просто хочу бросить мой на забаву.

Один слой с использованием underscore's groupBy и методы карты.

_.map(_.groupBy(yourarray,function(element) { return element.id }),function(element) { return element[0] }); 

PD: принято ли распространять несколько ответов, когда они все правильны? возможно, я неосознанно нарушал этический этикет.

+1

['_.uniq'] (http://underscorejs.org/#uniq) лучше:' _.uniq (urls, function (url) {return url.id}); ':-) –

+0

замечательный. Я стою исправлено :) – amenadiel

Смежные вопросы